diff --git a/src/controller/datacontroller.js b/src/controller/datacontroller.js index a9cc4644a..f8d519573 100644 --- a/src/controller/datacontroller.js +++ b/src/controller/datacontroller.js @@ -149,7 +149,7 @@ export default class DataController { this.mapper.clearBindings(); // First, convert elements. - const modelRange = ModelRange.createIn( modelElementOrFragment ); + const modelRange = ModelRange._createIn( modelElementOrFragment ); const viewDocumentFragment = new ViewDocumentFragment(); @@ -227,7 +227,7 @@ export default class DataController { writer.setSelection( null ); writer.removeSelectionAttribute( this.model.document.selection.getAttributeKeys() ); - writer.remove( ModelRange.createIn( modelRoot ) ); + writer.remove( writer.createRangeIn( modelRoot ) ); writer.insert( this.parse( data, modelRoot ), modelRoot, 0 ); } ); } @@ -297,7 +297,7 @@ function _getMarkersRelativeToElement( element ) { return []; } - const elementRange = ModelRange.createIn( element ); + const elementRange = ModelRange._createIn( element ); for ( const marker of doc.model.markers ) { const intersection = elementRange.getIntersection( marker.getRange() ); diff --git a/src/conversion/downcast-converters.js b/src/conversion/downcast-converters.js index b91f3dca0..7424d75e0 100644 --- a/src/conversion/downcast-converters.js +++ b/src/conversion/downcast-converters.js @@ -8,7 +8,6 @@ import ModelSelection from '../model/selection'; import ModelElement from '../model/element'; import ViewAttributeElement from '../view/attributeelement'; -import ViewRange from '../view/range'; import DocumentSelection from '../model/documentselection'; import { cloneDeep } from 'lodash-es'; @@ -535,14 +534,14 @@ export function remove() { const modelEnd = data.position.getShiftedBy( data.length ); const viewEnd = conversionApi.mapper.toViewPosition( modelEnd, { isPhantom: true } ); - const viewRange = new ViewRange( viewStart, viewEnd ); + const viewRange = conversionApi.writer.createRange( viewStart, viewEnd ); // Trim the range to remove in case some UI elements are on the view range boundaries. const removed = conversionApi.writer.remove( viewRange.getTrimmed() ); // After the range is removed, unbind all view elements from the model. // Range inside view document fragment is used to unbind deeply. - for ( const child of ViewRange.createIn( removed ).getItems() ) { + for ( const child of conversionApi.writer.createRangeIn( removed ).getItems() ) { conversionApi.mapper.unbindViewElement( child ); } }; @@ -628,7 +627,7 @@ export function removeUIElement() { conversionApi.mapper.unbindElementsFromMarkerName( data.markerName ); for ( const element of elements ) { - conversionApi.writer.clear( ViewRange.createOn( element ), element ); + conversionApi.writer.clear( conversionApi.writer.createRangeOn( element ), element ); } conversionApi.writer.clearClonedElementsGroup( data.markerName ); @@ -903,7 +902,7 @@ export function highlightElement( highlightDescriptor ) { conversionApi.consumable.consume( data.item, evt.name ); // Consume all children nodes. - for ( const value of ModelRange.createIn( data.item ) ) { + for ( const value of ModelRange._createIn( data.item ) ) { conversionApi.consumable.consume( value.item, evt.name ); } @@ -965,7 +964,7 @@ export function removeHighlight( highlightDescriptor ) { for ( const element of elements ) { if ( element.is( 'attributeElement' ) ) { - conversionApi.writer.unwrap( ViewRange.createOn( element ), viewHighlightElement ); + conversionApi.writer.unwrap( conversionApi.writer.createRangeOn( element ), viewHighlightElement ); } else { // if element.is( 'containerElement' ). element.getCustomProperty( 'removeHighlight' )( element, descriptor.id, conversionApi.writer ); diff --git a/src/conversion/downcastdispatcher.js b/src/conversion/downcastdispatcher.js index 24eb7cf4b..2cabf09c7 100644 --- a/src/conversion/downcastdispatcher.js +++ b/src/conversion/downcastdispatcher.js @@ -131,7 +131,7 @@ export default class DowncastDispatcher { // Convert changes that happened on model tree. for ( const entry of differ.getChanges() ) { if ( entry.type == 'insert' ) { - this.convertInsert( Range.createFromPositionAndShift( entry.position, entry.length ), writer ); + this.convertInsert( Range._createFromPositionAndShift( entry.position, entry.length ), writer ); } else if ( entry.type == 'remove' ) { this.convertRemove( entry.position, entry.length, entry.name, writer ); } else { @@ -166,7 +166,7 @@ export default class DowncastDispatcher { // Fire a separate insert event for each node and text fragment contained in the range. for ( const value of range ) { const item = value.item; - const itemRange = Range.createFromPositionAndShift( value.previousPosition, value.length ); + const itemRange = Range._createFromPositionAndShift( value.previousPosition, value.length ); const data = { item, range: itemRange @@ -226,7 +226,7 @@ export default class DowncastDispatcher { // Create a separate attribute event for each node in the range. for ( const value of range ) { const item = value.item; - const itemRange = Range.createFromPositionAndShift( value.previousPosition, value.length ); + const itemRange = Range._createFromPositionAndShift( value.previousPosition, value.length ); const data = { item, range: itemRange, @@ -343,7 +343,7 @@ export default class DowncastDispatcher { continue; } - const data = { item, range: Range.createOn( item ), markerName, markerRange }; + const data = { item, range: Range._createOn( item ), markerName, markerRange }; this.fire( eventName, data, this.conversionApi ); } diff --git a/src/conversion/mapper.js b/src/conversion/mapper.js index 26c179ebd..100bfeb1f 100644 --- a/src/conversion/mapper.js +++ b/src/conversion/mapper.js @@ -101,7 +101,7 @@ export default class Mapper { const modelOffset = this._toModelOffset( data.viewPosition.parent, data.viewPosition.offset, viewBlock ); - data.modelPosition = ModelPosition.createFromParentAndOffset( modelParent, modelOffset ); + data.modelPosition = ModelPosition._createAt( modelParent, modelOffset ); }, { priority: 'low' } ); } diff --git a/src/conversion/upcast-converters.js b/src/conversion/upcast-converters.js index 0cc75a4f3..2caabdb10 100644 --- a/src/conversion/upcast-converters.js +++ b/src/conversion/upcast-converters.js @@ -6,7 +6,6 @@ import Matcher from '../view/matcher'; import ModelRange from '../model/range'; -import ModelPosition from '../model/position'; import { cloneDeep } from 'lodash-es'; @@ -358,7 +357,7 @@ function _prepareToElementConverter( config ) { conversionApi.writer.insert( modelElement, splitResult.position ); // Convert children and insert to element. - const childrenResult = conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( modelElement, 0 ) ); + const childrenResult = conversionApi.convertChildren( data.viewItem, conversionApi.writer.createPositionAt( modelElement, 0 ) ); // Consume appropriate value from consumable values list. conversionApi.consumable.consume( data.viewItem, match.match ); @@ -366,12 +365,12 @@ function _prepareToElementConverter( config ) { // Set conversion result range. data.modelRange = new ModelRange( // Range should start before inserted element - ModelPosition.createBefore( modelElement ), + conversionApi.writer.createPositionBefore( modelElement ), // Should end after but we need to take into consideration that children could split our // element, so we need to move range after parent of the last converted child. // before: [] // after: [] - ModelPosition.createAfter( childrenResult.modelCursor.parent ) + conversionApi.writer.createPositionAfter( childrenResult.modelCursor.parent ) ); // Now we need to check where the modelCursor should be. @@ -380,7 +379,7 @@ function _prepareToElementConverter( config ) { // before: [] // after: [] if ( splitResult.cursorParent ) { - data.modelCursor = ModelPosition.createAt( splitResult.cursorParent, 0 ); + data.modelCursor = conversionApi.writer.createPositionAt( splitResult.cursorParent, 0 ); // Otherwise just continue after inserted element. } else { @@ -602,7 +601,7 @@ export function convertText() { conversionApi.writer.insert( text, data.modelCursor ); - data.modelRange = ModelRange.createFromPositionAndShift( data.modelCursor, text.offsetSize ); + data.modelRange = ModelRange._createFromPositionAndShift( data.modelCursor, text.offsetSize ); data.modelCursor = data.modelRange.end; } } diff --git a/src/conversion/upcastdispatcher.js b/src/conversion/upcastdispatcher.js index a95c10da5..39c49656e 100644 --- a/src/conversion/upcastdispatcher.js +++ b/src/conversion/upcastdispatcher.js @@ -71,10 +71,16 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix'; * conversionApi.writer.insert( paragraph, splitResult.position ); * * // Convert children to paragraph. - * const { modelRange } = conversionApi.convertChildren( data.viewItem, Position.createAt( paragraph, 0 ) ); + * const { modelRange } = conversionApi.convertChildren( + * data.viewItem, + * conversionApi.writer.createPositionAt( paragraph, 0 ) + * ); * * // Set as conversion result, attribute converters may use this property. - * data.modelRange = new Range( Position.createBefore( paragraph ), modelRange.end ); + * data.modelRange = conversionApi.writer.createRange( + * conversionApi.writer.createPositionBefore( paragraph ), + * modelRange.end + * ); * * // Continue conversion inside paragraph. * data.modelCursor = data.modelRange.end; @@ -372,7 +378,7 @@ function extractMarkersFromModelFragment( modelItem, writer ) { const markers = new Map(); // Create ModelTreeWalker. - const range = ModelRange.createIn( modelItem ).getItems(); + const range = ModelRange._createIn( modelItem ).getItems(); // Walk through DocumentFragment and collect marker elements. for ( const item of range ) { @@ -385,14 +391,14 @@ function extractMarkersFromModelFragment( modelItem, writer ) { // Walk through collected marker elements store its path and remove its from the DocumentFragment. for ( const markerElement of markerElements ) { const markerName = markerElement.getAttribute( 'data-name' ); - const currentPosition = ModelPosition.createBefore( markerElement ); + const currentPosition = writer.createPositionBefore( markerElement ); // When marker of given name is not stored it means that we have found the beginning of the range. if ( !markers.has( markerName ) ) { - markers.set( markerName, new ModelRange( ModelPosition.createFromPosition( currentPosition ) ) ); + markers.set( markerName, new ModelRange( currentPosition.clone() ) ); // Otherwise is means that we have found end of the marker range. } else { - markers.get( markerName ).end = ModelPosition.createFromPosition( currentPosition ); + markers.get( markerName ).end = currentPosition.clone(); } // Remove marker element from DocumentFragment. @@ -419,7 +425,7 @@ function createContextTree( contextDefinition, writer ) { writer.append( current, position ); } - position = ModelPosition.createAt( current, 0 ); + position = ModelPosition._createAt( current, 0 ); } return position; diff --git a/src/dev-utils/enableenginedebug.js b/src/dev-utils/enableenginedebug.js index 09c851d4d..063eba2ee 100644 --- a/src/dev-utils/enableenginedebug.js +++ b/src/dev-utils/enableenginedebug.js @@ -311,7 +311,7 @@ function enableLoggingTools() { } ); sandbox.mock( DetachOperation.prototype, 'toString', function() { - const range = ModelRange.createFromPositionAndShift( this.sourcePosition, this.howMany ); + const range = ModelRange._createFromPositionAndShift( this.sourcePosition, this.howMany ); const nodes = Array.from( range.getItems() ); const nodeString = nodes.length > 1 ? `[ ${ nodes.length } ]` : nodes[ 0 ]; @@ -330,7 +330,7 @@ function enableLoggingTools() { } ); sandbox.mock( MoveOperation.prototype, 'toString', function() { - const range = ModelRange.createFromPositionAndShift( this.sourcePosition, this.howMany ); + const range = ModelRange._createFromPositionAndShift( this.sourcePosition, this.howMany ); return getClassName( this ) + `( ${ this.baseVersion } ): ${ range } -> ${ this.targetPosition }`; } ); diff --git a/src/dev-utils/model.js b/src/dev-utils/model.js index 3bb88fdd2..567e8bad8 100644 --- a/src/dev-utils/model.js +++ b/src/dev-utils/model.js @@ -115,7 +115,7 @@ export function setData( model, data, options = {} ) { model.change( writer => { // Replace existing model in document by new one. - writer.remove( ModelRange.createIn( modelRoot ) ); + writer.remove( writer.createRangeIn( modelRoot ) ); writer.insert( modelDocumentFragment, modelRoot ); // Clean up previous document selection. @@ -169,16 +169,16 @@ export function stringify( node, selectionOrPositionOrRange = null, markers = nu // Create a range witch wraps passed node. if ( node instanceof RootElement || node instanceof ModelDocumentFragment ) { - range = ModelRange.createIn( node ); + range = model.createRangeIn( node ); } else { // Node is detached - create new document fragment. if ( !node.parent ) { const fragment = new ModelDocumentFragment( node ); - range = ModelRange.createIn( fragment ); + range = model.createRangeIn( fragment ); } else { range = new ModelRange( - ModelPosition.createBefore( node ), - ModelPosition.createAfter( node ) + model.createPositionBefore( node ), + model.createPositionAfter( node ) ); } } @@ -391,9 +391,9 @@ function convertToModelElement() { conversionApi.mapper.bindElements( element, data.viewItem ); - conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( element, 0 ) ); + conversionApi.convertChildren( data.viewItem, ModelPosition._createAt( element, 0 ) ); - data.modelRange = ModelRange.createOn( element ); + data.modelRange = ModelRange._createOn( element ); data.modelCursor = data.modelRange.end; evt.stop(); @@ -420,7 +420,7 @@ function convertToModelText( withAttributes = false ) { conversionApi.writer.insert( node, data.modelCursor ); - data.modelRange = ModelRange.createFromPositionAndShift( data.modelCursor, node.offsetSize ); + data.modelRange = ModelRange._createFromPositionAndShift( data.modelCursor, node.offsetSize ); data.modelCursor = data.modelRange.end; evt.stop(); diff --git a/src/dev-utils/view.js b/src/dev-utils/view.js index ad7e0f528..75b25096f 100644 --- a/src/dev-utils/view.js +++ b/src/dev-utils/view.js @@ -138,7 +138,7 @@ setData._parse = parse; * const b = new Element( 'b', null, text ); * const p = new Element( 'p', null, b ); * const selection = new Selection( - * Range.createFromParentsAndOffsets( p, 0, p, 1 ) + * Range._createFromParentsAndOffsets( p, 0, p, 1 ) * ); * * stringify( p, selection ); // '

[foobar]

' @@ -148,7 +148,7 @@ setData._parse = parse; * const text = new Text( 'foobar' ); * const b = new Element( 'b', null, text ); * const p = new Element( 'p', null, b ); - * const selection = new Selection( Range.createFromParentsAndOffsets( text, 1, text, 5 ) ); + * const selection = new Selection( Range._createFromParentsAndOffsets( text, 1, text, 5 ) ); * * stringify( p, selection ); // '

f{ooba}r

' * @@ -161,8 +161,8 @@ setData._parse = parse; * * const text = new Text( 'foobar' ); * const selection = new Selection( [ - * Range.createFromParentsAndOffsets( text, 0, text, 1 ) ), - * Range.createFromParentsAndOffsets( text, 3, text, 5 ) ) + * Range._createFromParentsAndOffsets( text, 0, text, 1 ) ), + * Range._createFromParentsAndOffsets( text, 3, text, 5 ) ) * ] ); * * stringify( text, selection ); // '{f}oo{ba}r' @@ -173,7 +173,7 @@ setData._parse = parse; * be converted to a selection containing one range collapsed at this position. * * const text = new Text( 'foobar' ); - * const range = Range.createFromParentsAndOffsets( text, 0, text, 1 ); + * const range = Range._createFromParentsAndOffsets( text, 0, text, 1 ); * const position = new Position( text, 3 ); * * stringify( text, range ); // '{f}oobar' diff --git a/src/model/differ.js b/src/model/differ.js index 69ab36b51..07e803c17 100644 --- a/src/model/differ.js +++ b/src/model/differ.js @@ -170,7 +170,7 @@ export default class Differ { this._markRemove( operation.position.parent, operation.position.offset, 1 ); this._markInsert( operation.position.parent, operation.position.offset, 1 ); - const range = Range.createFromPositionAndShift( operation.position, 1 ); + const range = Range._createFromPositionAndShift( operation.position, 1 ); for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) { const markerRange = marker.getRange(); @@ -391,10 +391,10 @@ export default class Differ { let range; if ( elementChildren[ i ].name == '$text' ) { - range = Range.createFromParentsAndOffsets( element, i, element, i + 1 ); + range = new Range( Position._createAt( element, i ), Position._createAt( element, i + 1 ) ); } else { const index = element.offsetToIndex( i ); - range = Range.createFromParentsAndOffsets( element, i, element.getChild( index ), 0 ); + range = new Range( Position._createAt( element, i ), Position._createAt( element.getChild( index ), 0 ) ); } // Generate diff items for this change (there might be multiple attributes changed and @@ -826,7 +826,7 @@ export default class Differ { _getInsertDiff( parent, offset, name ) { return { type: 'insert', - position: Position.createFromParentAndOffset( parent, offset ), + position: Position._createAt( parent, offset ), name, length: 1, changeCount: this._changeCount++ @@ -845,7 +845,7 @@ export default class Differ { _getRemoveDiff( parent, offset, name ) { return { type: 'remove', - position: Position.createFromParentAndOffset( parent, offset ), + position: Position._createAt( parent, offset ), name, length: 1, changeCount: this._changeCount++ @@ -879,7 +879,7 @@ export default class Differ { diffs.push( { type: 'attribute', position: range.start, - range: Range.createFromRange( range ), + range: range.clone(), length: 1, attributeKey: key, attributeOldValue: oldValue, @@ -898,7 +898,7 @@ export default class Differ { diffs.push( { type: 'attribute', position: range.start, - range: Range.createFromRange( range ), + range: range.clone(), length: 1, attributeKey: key, attributeOldValue: null, @@ -948,7 +948,7 @@ export default class Differ { * @param {Number} howMany */ _removeAllNestedChanges( parent, offset, howMany ) { - const range = Range.createFromParentsAndOffsets( parent, offset, parent, offset + howMany ); + const range = new Range( Position._createAt( parent, offset ), Position._createAt( parent, offset + howMany ) ); for ( const item of range.getItems( { shallow: true } ) ) { if ( item.is( 'element' ) ) { diff --git a/src/model/document.js b/src/model/document.js index d743def3c..61b0a3143 100644 --- a/src/model/document.js +++ b/src/model/document.js @@ -8,8 +8,6 @@ */ import Differ from './differ'; -import Range from './range'; -import Position from './position'; import RootElement from './rootelement'; import History from './history'; import DocumentSelection from './documentselection'; @@ -334,14 +332,15 @@ export default class Document { */ _getDefaultRange() { const defaultRoot = this._getDefaultRoot(); - const schema = this.model.schema; + const model = this.model; + const schema = model.schema; // Find the first position where the selection can be put. - const position = new Position( defaultRoot, [ 0 ] ); + const position = model.createPositionFromPath( defaultRoot, [ 0 ] ); const nearestRange = schema.getNearestSelectionRange( position ); // If valid selection range is not found - return range collapsed at the beginning of the root. - return nearestRange || new Range( position ); + return nearestRange || model.createRange( position ); } /** diff --git a/src/model/documentselection.js b/src/model/documentselection.js index 3a472dc7d..dbe4516b3 100644 --- a/src/model/documentselection.js +++ b/src/model/documentselection.js @@ -11,7 +11,6 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix'; import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin'; import Selection from './selection'; -import Position from './position'; import LiveRange from './liverange'; import Text from './text'; import TextProxy from './textproxy'; @@ -332,7 +331,8 @@ export default class DocumentSelection { * Moves {@link module:engine/model/documentselection~DocumentSelection#focus} to the specified location. * Should be used only within the {@link module:engine/model/writer~Writer#setSelectionFocus} method. * - * The location can be specified in the same form as {@link module:engine/model/position~Position.createAt} parameters. + * The location can be specified in the same form as + * {@link module:engine/model/writer~Writer#createPositionAt writer.createPositionAt()} parameters. * * @see module:engine/model/writer~Writer#setSelectionFocus * @protected @@ -750,7 +750,7 @@ class LiveSelection extends Selection { return; } - const liveRange = LiveRange.createFromRange( range ); + const liveRange = LiveRange.fromRange( range ); liveRange.on( 'change:range', ( evt, oldRange, data ) => { this._hasChangedRange = true; @@ -1014,7 +1014,7 @@ class LiveSelection extends Selection { _fixGraveyardSelection( liveRange, removedRangeStart ) { // The start of the removed range is the closest position to the `liveRange` - the original selection range. // This is a good candidate for a fixed selection range. - const positionCandidate = Position.createFromPosition( removedRangeStart ); + const positionCandidate = removedRangeStart.clone(); // Find a range that is a correct selection range and is closest to the start of removed range. const selectionRange = this._model.schema.getNearestSelectionRange( positionCandidate ); diff --git a/src/model/liveposition.js b/src/model/liveposition.js index edd946423..57a8edbac 100644 --- a/src/model/liveposition.js +++ b/src/model/liveposition.js @@ -63,35 +63,40 @@ export default class LivePosition extends Position { } /** - * @static - * @method module:engine/model/liveposition~LivePosition.createAfter - * @see module:engine/model/position~Position.createAfter - * @param {module:engine/model/node~Node} node - * @returns {module:engine/model/liveposition~LivePosition} + * Creates a {@link module:engine/model/position~Position position instance}, which is equal to this live position. + * + * @returns {module:engine/model/position~Position} */ + toPosition() { + return new Position( this.root, this.path.slice(), this.stickiness ); + } /** - * @static - * @method module:engine/model/liveposition~LivePosition.createBefore - * @see module:engine/model/position~Position.createBefore - * @param {module:engine/model/node~Node} node - * @returns {module:engine/model/liveposition~LivePosition} + * Creates a `LivePosition` instance that is equal to position. + * + * @param {module:engine/model/position~Position} position + * @param {module:engine/model/position~PositionStickiness} [stickiness] + * @returns {module:engine/model/position~Position} */ + static fromPosition( position, stickiness ) { + return new this( position.root, position.path.slice(), stickiness ? stickiness : position.stickiness ); + } /** * @static - * @method module:engine/model/liveposition~LivePosition.createFromParentAndOffset - * @see module:engine/model/position~Position.createFromParentAndOffset - * @param {module:engine/model/element~Element} parent - * @param {Number} offset + * @protected + * @method module:engine/model/liveposition~LivePosition._createAfter + * @see module:engine/model/position~Position._createAfter + * @param {module:engine/model/node~Node} node * @returns {module:engine/model/liveposition~LivePosition} */ /** * @static - * @method module:engine/model/liveposition~LivePosition.createFromPosition - * @see module:engine/model/position~Position.createFromPosition - * @param {module:engine/model/position~Position} position + * @protected + * @method module:engine/model/liveposition~LivePosition._createBefore + * @see module:engine/model/position~Position._createBefore + * @param {module:engine/model/node~Node} node * @returns {module:engine/model/liveposition~LivePosition} */ @@ -132,7 +137,7 @@ function transform( operation ) { const result = this.getTransformedByOperation( operation ); if ( !this.isEqual( result ) ) { - const oldPosition = Position.createFromPosition( this ); + const oldPosition = this.toPosition(); this.path = result.path; this.root = result.root; diff --git a/src/model/liverange.js b/src/model/liverange.js index 2865df682..de28ab9dd 100644 --- a/src/model/liverange.js +++ b/src/model/liverange.js @@ -41,38 +41,49 @@ export default class LiveRange extends Range { } /** - * @see module:engine/model/range~Range.createIn - * @static - * @method module:engine/model/liverange~LiveRange.createIn - * @param {module:engine/model/element~Element} element + * Creates a {@link module:engine/model/range~Range range instance} that is equal to this live range. + * + * @returns {module:engine/model/range~Range} + */ + toRange() { + return new Range( this.start, this.end ); + } + + /** + * Creates a `LiveRange` instance that is equal to the given range. + * + * @param {module:engine/model/range~Range} range * @returns {module:engine/model/liverange~LiveRange} */ + static fromRange( range ) { + return new LiveRange( range.start, range.end ); + } /** - * @see module:engine/model/range~Range.createFromPositionAndShift + * @see module:engine/model/range~Range._createIn * @static - * @method module:engine/model/liverange~LiveRange.createFromPositionAndShift - * @param {module:engine/model/position~Position} position - * @param {Number} shift + * @protected + * @method module:engine/model/liverange~LiveRange._createIn + * @param {module:engine/model/element~Element} element * @returns {module:engine/model/liverange~LiveRange} */ /** - * @see module:engine/model/range~Range.createFromParentsAndOffsets + * @see module:engine/model/range~Range._createOn * @static - * @method module:engine/model/liverange~LiveRange.createFromParentsAndOffsets - * @param {module:engine/model/element~Element} startElement - * @param {Number} startOffset - * @param {module:engine/model/element~Element} endElement - * @param {Number} endOffset + * @protected + * @method module:engine/model/liverange~LiveRange._createOn + * @param {module:engine/model/element~Element} element * @returns {module:engine/model/liverange~LiveRange} */ /** - * @see module:engine/model/range~Range.createFromRange + * @see module:engine/model/range~Range._createFromPositionAndShift * @static - * @method module:engine/model/liverange~LiveRange.createFromRange - * @param {module:engine/model/range~Range} range + * @protected + * @method module:engine/model/liverange~LiveRange._createFromPositionAndShift + * @param {module:engine/model/position~Position} position + * @param {Number} shift * @returns {module:engine/model/liverange~LiveRange} */ @@ -129,7 +140,7 @@ function bindWithDocument() { function transform( operation ) { // Transform the range by the operation. Join the result ranges if needed. const ranges = this.getTransformedByOperation( operation ); - const result = Range.createFromRanges( ranges ); + const result = Range._createFromRanges( ranges ); const boundariesChanged = !result.isEqual( this ); const contentChanged = doesOperationChangeRangeContent( this, operation ); @@ -149,7 +160,7 @@ function transform( operation ) { } } - const oldRange = Range.createFromRange( this ); + const oldRange = this.toRange(); this.start = result.start; this.end = result.end; @@ -157,7 +168,7 @@ function transform( operation ) { this.fire( 'change:range', oldRange, { deletionPosition } ); } else if ( contentChanged ) { // If range boundaries have not changed, but there was change inside the range, fire `change:content` event. - this.fire( 'change:content', Range.createFromRange( this ), { deletionPosition } ); + this.fire( 'change:content', this.toRange(), { deletionPosition } ); } } diff --git a/src/model/markercollection.js b/src/model/markercollection.js index 3662efb48..63411115d 100644 --- a/src/model/markercollection.js +++ b/src/model/markercollection.js @@ -8,8 +8,6 @@ */ import LiveRange from './liverange'; -import Position from './position'; -import Range from './range'; import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import mix from '@ckeditor/ckeditor5-utils/src/mix'; @@ -101,7 +99,7 @@ export default class MarkerCollection { let hasChanged = false; if ( !oldRange.isEqual( range ) ) { - oldMarker._attachLiveRange( LiveRange.createFromRange( range ) ); + oldMarker._attachLiveRange( LiveRange.fromRange( range ) ); hasChanged = true; } @@ -122,7 +120,7 @@ export default class MarkerCollection { return oldMarker; } - const liveRange = LiveRange.createFromRange( range ); + const liveRange = LiveRange.fromRange( range ); const marker = new Marker( markerName, liveRange, managedUsingOperations, affectsData ); this._markers.set( markerName, marker ); @@ -396,7 +394,7 @@ class Marker { throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.' ); } - return Position.createFromPosition( this._liveRange.start ); + return this._liveRange.start.clone(); } /** @@ -409,7 +407,7 @@ class Marker { throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.' ); } - return Position.createFromPosition( this._liveRange.end ); + return this._liveRange.end.clone(); } /** @@ -429,7 +427,7 @@ class Marker { throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.' ); } - return Range.createFromRange( this._liveRange ); + return this._liveRange.toRange(); } /** diff --git a/src/model/model.js b/src/model/model.js index b27392fe1..ec2262f5c 100644 --- a/src/model/model.js +++ b/src/model/model.js @@ -16,6 +16,8 @@ import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin'; import mix from '@ckeditor/ckeditor5-utils/src/mix'; import ModelElement from './element'; import ModelRange from './range'; +import ModelPosition from './position'; +import ModelSelection from './selection'; import insertContent from './utils/insertcontent'; import deleteContent from './utils/deletecontent'; @@ -310,16 +312,16 @@ export default class Model { * editor.model.insertContent( writer.createText( 'x' ), doc.getRoot(), 2 ); * * // Which is a shorthand for: - * editor.model.insertContent( writer.createText( 'x' ), Position.createAt( doc.getRoot(), 2 ) ); + * editor.model.insertContent( writer.createText( 'x' ), writer.createPositionAt( doc.getRoot(), 2 ) ); * } ); * * If an instance of {@link module:engine/model/selection~Selection} is passed as `selectable` * it will be moved to the target position (where the document selection should be moved after the insertion). * - * // Insert text replacing the given selection instance. - * const selection = new Selection( paragraph, 'in' ); - * * editor.model.change( writer => { + * // Insert text replacing the given selection instance. + * const selection = writer.createSelection( paragraph, 'in' ); + * * editor.model.insertContent( writer.createText( 'x' ), selection ); * * // insertContent() modifies the passed selection instance so it can be used to set the document selection. @@ -444,17 +446,18 @@ export default class Model { } /** - * Checks whether given {@link module:engine/model/range~Range range} or {@link module:engine/model/element~Element element} + * Checks whether the given {@link module:engine/model/range~Range range} or + * {@link module:engine/model/element~Element element} * has any content. * - * Content is any text node or element which is registered in {@link module:engine/model/schema~Schema schema}. + * Content is any text node or element which is registered in the {@link module:engine/model/schema~Schema schema}. * * @param {module:engine/model/range~Range|module:engine/model/element~Element} rangeOrElement Range or element to check. * @returns {Boolean} */ hasContent( rangeOrElement ) { if ( rangeOrElement instanceof ModelElement ) { - rangeOrElement = ModelRange.createIn( rangeOrElement ); + rangeOrElement = ModelRange._createIn( rangeOrElement ); } if ( rangeOrElement.isCollapsed ) { @@ -471,6 +474,208 @@ export default class Model { return false; } + /** + * Creates a position from the given root and path in that root. + * + * Note: This method is also available as + * {@link module:engine/model/writer~Writer#createPositionFromPath `Writer#createPositionFromPath()`}. + * + * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} root Root of the position. + * @param {Array.} path Position path. See {@link module:engine/model/position~Position#path}. + * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness. + * See {@link module:engine/model/position~PositionStickiness}. + * @returns {module:engine/model/position~Position} + */ + createPositionFromPath( root, path, stickiness ) { + return new ModelPosition( root, path, stickiness ); + } + + /** + * Creates position at the given location. The location can be specified as: + * + * * a {@link module:engine/model/position~Position position}, + * * a parent element and offset in that element, + * * a parent element and `'end'` (the position will be set at the end of that element), + * * a {@link module:engine/model/item~Item model item} and `'before'` or `'after'` + * (the position will be set before or after the given model item). + * + * This method is a shortcut to other factory methods such as: + * + * * {@link module:engine/model/model~Model#createPositionBefore `createPositionBefore()`}, + * * {@link module:engine/model/model~Model#createPositionAfter `createPositionAfter()`}. + * + * Note: This method is also available as + * {@link module:engine/model/writer~Writer#createPositionAt `Writer#createPositionAt()`}, + * + * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition + * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when + * first parameter is a {@link module:engine/model/item~Item model item}. + */ + createPositionAt( itemOrPosition, offset ) { + return ModelPosition._createAt( itemOrPosition, offset ); + } + + /** + * Creates a new position after the given {@link module:engine/model/item~Item model item}. + * + * Note: This method is also available as + * {@link module:engine/model/writer~Writer#createPositionAfter `Writer#createPositionAfter()`}. + * + * @param {module:engine/model/item~Item} item Item after which the position should be placed. + * @returns {module:engine/model/position~Position} + */ + createPositionAfter( item ) { + return ModelPosition._createAfter( item ); + } + + /** + * Creates a new position before the given {@link module:engine/model/item~Item model item}. + * + * Note: This method is also available as + * {@link module:engine/model/writer~Writer#createPositionBefore `Writer#createPositionBefore()`}. + * + * @param {module:engine/model/item~Item} item Item before which the position should be placed. + * @returns {module:engine/model/position~Position} + */ + createPositionBefore( item ) { + return ModelPosition._createBefore( item ); + } + + /** + * Creates a range spanning from the `start` position to the `end` position. + * + * Note: This method is also available as + * {@link module:engine/model/writer~Writer#createRange `Writer#createRange()`}: + * + * model.change( writer => { + * const range = writer.createRange( start, end ); + * } ); + * + * @param {module:engine/model/position~Position} start Start position. + * @param {module:engine/model/position~Position} [end] End position. If not set, the range will be collapsed + * to the `start` position. + * @returns {module:engine/model/range~Range} + */ + createRange( start, end ) { + return new ModelRange( start, end ); + } + + /** + * Creates a range inside the given element which starts before the first child of + * that element and ends after the last child of that element. + * + * Note: This method is also available as + * {@link module:engine/model/writer~Writer#createRangeIn `Writer#createRangeIn()`}: + * + * model.change( writer => { + * const range = writer.createRangeIn( paragraph ); + * } ); + * + * @param {module:engine/model/element~Element} element Element which is a parent for the range. + * @returns {module:engine/model/range~Range} + */ + createRangeIn( element ) { + return ModelRange._createIn( element ); + } + + /** + * Creates a range that starts before the given {@link module:engine/model/item~Item model item} and ends after it. + * + * Note: This method is also available on `writer` instance as + * {@link module:engine/model/writer~Writer#createRangeOn `Writer.createRangeOn()`}: + * + * model.change( writer => { + * const range = writer.createRangeOn( paragraph ); + * } ); + * + * @param {module:engine/model/item~Item} item + * @returns {module:engine/model/range~Range} + */ + createRangeOn( item ) { + return ModelRange._createOn( item ); + } + + /** + * Creates a new selection instance based on: + * + * * the given {@link module:engine/model/selection~Selection selection}, + * * or based on the given {@link module:engine/model/range~Range range}, + * * or based on the given iterable collection of {@link module:engine/model/range~Range ranges} + * * or at the given {@link module:engine/model/position~Position position}, + * * or on the given {@link module:engine/model/element~Element element}, + * * or creates an empty selection if no arguments were passed. + * + * Note: This method is also available as + * {@link module:engine/model/writer~Writer#createSelection `Writer#createSelection()`}. + * + * // Creates empty selection without ranges. + * const selection = writer.createSelection(); + * + * // Creates selection at the given range. + * const range = writer.createRange( start, end ); + * const selection = writer.createSelection( range ); + * + * // Creates selection at the given ranges + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; + * const selection = writer.createSelection( ranges ); + * + * // Creates selection from the other selection. + * // Note: It doesn't copies selection attributes. + * const otherSelection = writer.createSelection(); + * const selection = writer.createSelection( otherSelection ); + * + * // Creates selection from the given document selection. + * // Note: It doesn't copies selection attributes. + * const documentSelection = model.document.selection; + * const selection = writer.createSelection( documentSelection ); + * + * // Creates selection at the given position. + * const position = writer.createPositionFromPath( root, path ); + * const selection = writer.createSelection( position ); + * + * // Creates selection at the given offset in the given element. + * const paragraph = writer.createElement( 'paragraph' ); + * const selection = writer.createSelection( paragraph, offset ); + * + * // Creates a range inside an {@link module:engine/model/element~Element element} which starts before the + * // first child of that element and ends after the last child of that element. + * const selection = writer.createSelection( paragraph, 'in' ); + * + * // Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends + * // just after the item. + * const selection = writer.createSelection( paragraph, 'on' ); + * + * // Additional options (`'backward'`) can be specified as the last argument. + * + * // Creates backward selection. + * const selection = writer.createSelection( range, { backward: true } ); + * + * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection| + * module:engine/model/position~Position|module:engine/model/element~Element| + * Iterable.|module:engine/model/range~Range|null} selectable + * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection. + * @param {Object} [options] + * @param {Boolean} [options.backward] Sets this selection instance to be backward. + * @returns {module:engine/model/selection~Selection} + */ + createSelection( selectable, placeOrOffset, options ) { + return new ModelSelection( selectable, placeOrOffset, options ); + } + + /** + * Creates a {@link module:engine/model/batch~Batch} instance. + * + * **Note:** In most cases creating a batch instance is not necessary as they are created when using: + * + * * {@link #change `change()`}, + * * {@link #enqueueChange `enqueueChange()`}. + * + * @returns {module:engine/model/batch~Batch} + */ + createBatch() { + return new Batch(); + } + /** * Removes all events listeners set by model instance and destroys {@link module:engine/model/document~Document}. */ diff --git a/src/model/operation/attributeoperation.js b/src/model/operation/attributeoperation.js index 3e7e22076..bb72c44c7 100644 --- a/src/model/operation/attributeoperation.js +++ b/src/model/operation/attributeoperation.js @@ -49,7 +49,7 @@ export default class AttributeOperation extends Operation { * @readonly * @member {module:engine/model/range~Range} */ - this.range = Range.createFromRange( range ); + this.range = range.clone(); /** * Key of an attribute to change or remove. diff --git a/src/model/operation/detachoperation.js b/src/model/operation/detachoperation.js index 6ef0a6d8a..6ea809dd5 100644 --- a/src/model/operation/detachoperation.js +++ b/src/model/operation/detachoperation.js @@ -8,7 +8,6 @@ */ import Operation from './operation'; -import Position from '../position'; import Range from '../range'; import { _remove } from './utils'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; @@ -36,7 +35,7 @@ export default class DetachOperation extends Operation { * * @member {module:engine/model/position~Position} #sourcePosition */ - this.sourcePosition = Position.createFromPosition( sourcePosition ); + this.sourcePosition = sourcePosition.clone(); /** * Offset size of moved range. @@ -82,7 +81,7 @@ export default class DetachOperation extends Operation { * @inheritDoc */ _execute() { - _remove( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ) ); + _remove( Range._createFromPositionAndShift( this.sourcePosition, this.howMany ) ); } /** diff --git a/src/model/operation/insertoperation.js b/src/model/operation/insertoperation.js index 9cf79012f..da2decb61 100644 --- a/src/model/operation/insertoperation.js +++ b/src/model/operation/insertoperation.js @@ -39,7 +39,7 @@ export default class InsertOperation extends Operation { * @readonly * @member {module:engine/model/position~Position} module:engine/model/operation/insertoperation~InsertOperation#position */ - this.position = Position.createFromPosition( position ); + this.position = position.clone(); this.position.stickiness = 'toNone'; /** diff --git a/src/model/operation/markeroperation.js b/src/model/operation/markeroperation.js index 6d43d925a..9786a023b 100644 --- a/src/model/operation/markeroperation.js +++ b/src/model/operation/markeroperation.js @@ -41,7 +41,7 @@ export default class MarkerOperation extends Operation { * @readonly * @member {module:engine/model/range~Range} */ - this.oldRange = oldRange ? Range.createFromRange( oldRange ) : null; + this.oldRange = oldRange ? oldRange.clone() : null; /** * Marker range after the change. @@ -49,7 +49,7 @@ export default class MarkerOperation extends Operation { * @readonly * @member {module:engine/model/range~Range} */ - this.newRange = newRange ? Range.createFromRange( newRange ) : null; + this.newRange = newRange ? newRange.clone() : null; /** * Specifies whether the marker operation affects the data produced by the data pipeline diff --git a/src/model/operation/mergeoperation.js b/src/model/operation/mergeoperation.js index e017e6130..798646910 100644 --- a/src/model/operation/mergeoperation.js +++ b/src/model/operation/mergeoperation.js @@ -45,7 +45,7 @@ export default class MergeOperation extends Operation { * * @member {module:engine/model/position~Position} module:engine/model/operation/mergeoperation~MergeOperation#sourcePosition */ - this.sourcePosition = Position.createFromPosition( sourcePosition ); + this.sourcePosition = sourcePosition.clone(); // This is, and should always remain, the first position in its parent. this.sourcePosition.stickiness = 'toPrevious'; @@ -61,7 +61,7 @@ export default class MergeOperation extends Operation { * * @member {module:engine/model/position~Position} module:engine/model/operation/mergeoperation~MergeOperation#targetPosition */ - this.targetPosition = Position.createFromPosition( targetPosition ); + this.targetPosition = targetPosition.clone(); // Except of a rare scenario in `MergeOperation` x `MergeOperation` transformation, // this is, and should always remain, the last position in its parent. this.targetPosition.stickiness = 'toNext'; @@ -71,7 +71,7 @@ export default class MergeOperation extends Operation { * * @member {module:engine/model/position~Position} module:engine/model/operation/mergeoperation~MergeOperation#graveyardPosition */ - this.graveyardPosition = Position.createFromPosition( graveyardPosition ); + this.graveyardPosition = graveyardPosition.clone(); } /** @@ -170,10 +170,10 @@ export default class MergeOperation extends Operation { */ _execute() { const mergedElement = this.sourcePosition.parent; - const sourceRange = Range.createIn( mergedElement ); + const sourceRange = Range._createIn( mergedElement ); _move( sourceRange, this.targetPosition ); - _move( Range.createOn( mergedElement ), this.graveyardPosition ); + _move( Range._createOn( mergedElement ), this.graveyardPosition ); } /** diff --git a/src/model/operation/moveoperation.js b/src/model/operation/moveoperation.js index 4873bb6bc..402cb7b42 100644 --- a/src/model/operation/moveoperation.js +++ b/src/model/operation/moveoperation.js @@ -40,7 +40,7 @@ export default class MoveOperation extends Operation { * * @member {module:engine/model/position~Position} module:engine/model/operation/moveoperation~MoveOperation#sourcePosition */ - this.sourcePosition = Position.createFromPosition( sourcePosition ); + this.sourcePosition = sourcePosition.clone(); // `'toNext'` because `sourcePosition` is a bit like a start of the moved range. this.sourcePosition.stickiness = 'toNext'; @@ -56,7 +56,7 @@ export default class MoveOperation extends Operation { * * @member {module:engine/model/position~Position} module:engine/model/operation/moveoperation~MoveOperation#targetPosition */ - this.targetPosition = Position.createFromPosition( targetPosition ); + this.targetPosition = targetPosition.clone(); this.targetPosition.stickiness = 'toNone'; } @@ -172,7 +172,7 @@ export default class MoveOperation extends Operation { * @inheritDoc */ _execute() { - _move( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ), this.targetPosition ); + _move( Range._createFromPositionAndShift( this.sourcePosition, this.howMany ), this.targetPosition ); } /** diff --git a/src/model/operation/renameoperation.js b/src/model/operation/renameoperation.js index d1a4eb9b7..5bf32c6b2 100644 --- a/src/model/operation/renameoperation.js +++ b/src/model/operation/renameoperation.js @@ -69,7 +69,7 @@ export default class RenameOperation extends Operation { * @returns {module:engine/model/operation/renameoperation~RenameOperation} Clone of this operation. */ clone() { - return new RenameOperation( Position.createFromPosition( this.position ), this.oldName, this.newName, this.baseVersion ); + return new RenameOperation( this.position.clone(), this.oldName, this.newName, this.baseVersion ); } /** @@ -78,7 +78,7 @@ export default class RenameOperation extends Operation { * @returns {module:engine/model/operation/renameoperation~RenameOperation} */ getReversed() { - return new RenameOperation( Position.createFromPosition( this.position ), this.newName, this.oldName, this.baseVersion + 1 ); + return new RenameOperation( this.position.clone(), this.newName, this.oldName, this.baseVersion + 1 ); } /** diff --git a/src/model/operation/splitoperation.js b/src/model/operation/splitoperation.js index 6884dbe80..8cf618647 100644 --- a/src/model/operation/splitoperation.js +++ b/src/model/operation/splitoperation.js @@ -41,7 +41,7 @@ export default class SplitOperation extends Operation { * * @member {module:engine/model/position~Position} module:engine/model/operation/splitoperation~SplitOperation#splitPosition */ - this.splitPosition = Position.createFromPosition( splitPosition ); + this.splitPosition = splitPosition.clone(); // Keep position sticking to the next node. This way any new content added at the place where the element is split // will be left in the original element. this.splitPosition.stickiness = 'toNext'; @@ -69,7 +69,7 @@ export default class SplitOperation extends Operation { * * @member {module:engine/model/position~Position|null} #graveyardPosition */ - this.graveyardPosition = graveyardPosition ? Position.createFromPosition( graveyardPosition ) : null; + this.graveyardPosition = graveyardPosition ? graveyardPosition.clone() : null; if ( this.graveyardPosition ) { this.graveyardPosition.stickiness = 'toNext'; @@ -181,15 +181,16 @@ export default class SplitOperation extends Operation { const splitElement = this.splitPosition.parent; if ( this.graveyardPosition ) { - _move( Range.createFromPositionAndShift( this.graveyardPosition, 1 ), this.insertionPosition ); + _move( Range._createFromPositionAndShift( this.graveyardPosition, 1 ), this.insertionPosition ); } else { const newElement = splitElement._clone(); _insert( this.insertionPosition, newElement ); } - const sourceRange = Range.createFromParentsAndOffsets( - splitElement, this.splitPosition.offset, splitElement, splitElement.maxOffset + const sourceRange = new Range( + Position._createAt( splitElement, this.splitPosition.offset ), + Position._createAt( splitElement, splitElement.maxOffset ) ); _move( sourceRange, this.moveTargetPosition ); diff --git a/src/model/operation/transform.js b/src/model/operation/transform.js index f2dd78341..0504f9d95 100644 --- a/src/model/operation/transform.js +++ b/src/model/operation/transform.js @@ -806,7 +806,7 @@ setTransformation( AttributeOperation, MergeOperation, ( a, b ) => { // if ( a.range.start.hasSameParentAs( b.deletionPosition ) ) { if ( a.range.containsPosition( b.deletionPosition ) || a.range.start.isEqual( b.deletionPosition ) ) { - ranges.push( Range.createFromPositionAndShift( b.graveyardPosition, 1 ) ); + ranges.push( Range._createFromPositionAndShift( b.graveyardPosition, 1 ) ); } } @@ -845,7 +845,7 @@ setTransformation( AttributeOperation, MoveOperation, ( a, b ) => { // @param {module:engine/model/operation/moveoperation~MoveOperation} moveOp // @returns {Array.} function _breakRangeByMoveOperation( range, moveOp ) { - const moveRange = Range.createFromPositionAndShift( moveOp.sourcePosition, moveOp.howMany ); + const moveRange = Range._createFromPositionAndShift( moveOp.sourcePosition, moveOp.howMany ); // We are transforming `range` (original range) by `moveRange` (range moved by move operation). As usual when it comes to // transforming a ranges, we may have a common part of the ranges and we may have a difference part (zero to two ranges). @@ -943,11 +943,11 @@ setTransformation( AttributeOperation, SplitOperation, ( a, b ) => { const secondPart = a.clone(); secondPart.range = new Range( - Position.createFromPosition( b.moveTargetPosition ), + b.moveTargetPosition.clone(), a.range.end._getCombined( b.splitPosition, b.moveTargetPosition ) ); - a.range.end = Position.createFromPosition( b.splitPosition ); + a.range.end = b.splitPosition.clone(); a.range.end.stickiness = 'toPrevious'; return [ a, secondPart ]; @@ -1047,7 +1047,7 @@ setTransformation( MarkerOperation, InsertOperation, ( a, b ) => { setTransformation( MarkerOperation, MarkerOperation, ( a, b, context ) => { if ( a.name == b.name ) { if ( context.aIsStrong ) { - a.oldRange = b.newRange ? Range.createFromRange( b.newRange ) : null; + a.oldRange = b.newRange ? b.newRange.clone() : null; } else { return [ new NoOperation( 0 ) ]; } @@ -1070,11 +1070,11 @@ setTransformation( MarkerOperation, MergeOperation, ( a, b ) => { setTransformation( MarkerOperation, MoveOperation, ( a, b ) => { if ( a.oldRange ) { - a.oldRange = Range.createFromRanges( a.oldRange._getTransformedByMoveOperation( b ) ); + a.oldRange = Range._createFromRanges( a.oldRange._getTransformedByMoveOperation( b ) ); } if ( a.newRange ) { - a.newRange = Range.createFromRanges( a.newRange._getTransformedByMoveOperation( b ) ); + a.newRange = Range._createFromRanges( a.newRange._getTransformedByMoveOperation( b ) ); } return [ a ]; @@ -1221,7 +1221,7 @@ setTransformation( MergeOperation, MoveOperation, ( a, b, context ) => { // // The exception of this rule would be if the remove operation was later undone. // - const removedRange = Range.createFromPositionAndShift( b.sourcePosition, b.howMany ); + const removedRange = Range._createFromPositionAndShift( b.sourcePosition, b.howMany ); if ( b.type == 'remove' && !context.bWasUndone ) { if ( a.deletionPosition.hasSameParentAs( b.sourcePosition ) && removedRange.containsPosition( a.sourcePosition ) ) { @@ -1348,7 +1348,7 @@ setTransformation( MergeOperation, SplitOperation, ( a, b, context ) => { // So now we are fixing situation which was skipped in `MergeOperation` x `MergeOperation` case. // if ( a.sourcePosition.isEqual( b.splitPosition ) && ( context.abRelation == 'mergeSameElement' || a.sourcePosition.offset > 0 ) ) { - a.sourcePosition = Position.createFromPosition( b.moveTargetPosition ); + a.sourcePosition = b.moveTargetPosition.clone(); a.targetPosition = a.targetPosition._getTransformedBySplitOperation( b ); return [ a ]; @@ -1369,7 +1369,7 @@ setTransformation( MergeOperation, SplitOperation, ( a, b, context ) => { // ----------------------- setTransformation( MoveOperation, InsertOperation, ( a, b ) => { - const moveRange = Range.createFromPositionAndShift( a.sourcePosition, a.howMany ); + const moveRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany ); const transformed = moveRange._getTransformedByInsertOperation( b, false )[ 0 ]; a.sourcePosition = transformed.start; @@ -1393,8 +1393,8 @@ setTransformation( MoveOperation, MoveOperation, ( a, b, context ) => { // Setting and evaluating some variables that will be used in special cases and default algorithm. // // Create ranges from `MoveOperations` properties. - const rangeA = Range.createFromPositionAndShift( a.sourcePosition, a.howMany ); - const rangeB = Range.createFromPositionAndShift( b.sourcePosition, b.howMany ); + const rangeA = Range._createFromPositionAndShift( a.sourcePosition, a.howMany ); + const rangeB = Range._createFromPositionAndShift( b.sourcePosition, b.howMany ); // Assign `context.aIsStrong` to a different variable, because the value may change during execution of // this algorithm and we do not want to override original `context.aIsStrong` that will be used in later transformations. @@ -1574,7 +1574,7 @@ setTransformation( MoveOperation, MoveOperation, ( a, b, context ) => { } ); setTransformation( MoveOperation, SplitOperation, ( a, b, context ) => { - let newTargetPosition = Position.createFromPosition( a.targetPosition ); + let newTargetPosition = a.targetPosition.clone(); // Do not transform if target position is same as split insertion position and this split comes from undo. // This should be done on relations but it is too much work for now as it would require relations working in collaboration. @@ -1590,7 +1590,7 @@ setTransformation( MoveOperation, SplitOperation, ( a, b, context ) => { // In this case the default range transformation will not work correctly as the element created by // split operation would be outside the range. The range to move needs to be fixed manually. // - const moveRange = Range.createFromPositionAndShift( a.sourcePosition, a.howMany ); + const moveRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany ); if ( moveRange.end.isEqual( b.insertionPosition ) ) { // Do it only if this is a "natural" split, not a one that comes from undo. @@ -1679,7 +1679,7 @@ setTransformation( MoveOperation, SplitOperation, ( a, b, context ) => { const movesGraveyardElement = moveRange.start.isEqual( b.graveyardPosition ) || moveRange.containsPosition( b.graveyardPosition ); if ( a.howMany > 1 && movesGraveyardElement ) { - ranges.push( Range.createFromPositionAndShift( b.insertionPosition, 1 ) ); + ranges.push( Range._createFromPositionAndShift( b.insertionPosition, 1 ) ); } } @@ -1687,7 +1687,7 @@ setTransformation( MoveOperation, SplitOperation, ( a, b, context ) => { } ); setTransformation( MoveOperation, MergeOperation, ( a, b, context ) => { - const movedRange = Range.createFromPositionAndShift( a.sourcePosition, a.howMany ); + const movedRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany ); if ( b.deletionPosition.hasSameParentAs( a.sourcePosition ) && movedRange.containsPosition( b.sourcePosition ) ) { if ( a.type == 'remove' ) { @@ -1703,8 +1703,8 @@ setTransformation( MoveOperation, MergeOperation, ( a, b, context ) => { if ( !context.aWasUndone ) { const results = []; - let gyMoveSource = Position.createFromPosition( b.graveyardPosition ); - let splitNodesMoveSource = Position.createFromPosition( b.targetPosition ); + let gyMoveSource = b.graveyardPosition.clone(); + let splitNodesMoveSource = b.targetPosition.clone(); if ( a.howMany > 1 ) { results.push( new MoveOperation( a.sourcePosition, a.howMany - 1, a.targetPosition, 0 ) ); @@ -1737,7 +1737,7 @@ setTransformation( MoveOperation, MergeOperation, ( a, b, context ) => { if ( !context.bWasUndone ) { return [ new NoOperation( 0 ) ]; } else { - a.sourcePosition = Position.createFromPosition( b.graveyardPosition ); + a.sourcePosition = b.graveyardPosition.clone(); a.targetPosition = a.targetPosition._getTransformedByMergeOperation( b ); return [ a ]; @@ -1748,7 +1748,7 @@ setTransformation( MoveOperation, MergeOperation, ( a, b, context ) => { // The default case. // - const moveRange = Range.createFromPositionAndShift( a.sourcePosition, a.howMany ); + const moveRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany ); const transformed = moveRange._getTransformedByMergeOperation( b ); a.sourcePosition = transformed.start; @@ -1772,7 +1772,7 @@ setTransformation( RenameOperation, MergeOperation, ( a, b ) => { // Element to rename got merged, so it was moved to `b.graveyardPosition`. // if ( a.position.isEqual( b.deletionPosition ) ) { - a.position = Position.createFromPosition( b.graveyardPosition ); + a.position = b.graveyardPosition.clone(); a.position.stickiness = 'toNext'; return [ a ]; @@ -1925,7 +1925,7 @@ setTransformation( SplitOperation, MergeOperation, ( a, b, context ) => { a.splitPosition = a.splitPosition._getTransformedByMergeOperation( b ); a.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition ); - a.graveyardPosition = Position.createFromPosition( additionalSplit.insertionPosition ); + a.graveyardPosition = additionalSplit.insertionPosition.clone(); a.graveyardPosition.stickiness = 'toNext'; return [ additionalSplit, a ]; @@ -1952,7 +1952,7 @@ setTransformation( SplitOperation, MergeOperation, ( a, b, context ) => { } ); setTransformation( SplitOperation, MoveOperation, ( a, b, context ) => { - const rangeToMove = Range.createFromPositionAndShift( b.sourcePosition, b.howMany ); + const rangeToMove = Range._createFromPositionAndShift( b.sourcePosition, b.howMany ); if ( a.graveyardPosition ) { // Case 1: @@ -2002,7 +2002,7 @@ setTransformation( SplitOperation, MoveOperation, ( a, b, context ) => { a.howMany += b.howMany; } - a.splitPosition = Position.createFromPosition( b.sourcePosition ); + a.splitPosition = b.sourcePosition.clone(); a.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition ); return [ a ]; diff --git a/src/model/position.js b/src/model/position.js index eef73ce79..565d752e3 100644 --- a/src/model/position.js +++ b/src/model/position.js @@ -16,20 +16,25 @@ import { last } from 'lodash-es'; /** * Represents a position in the model tree. * - * **Note:** Position is based on offsets, not indexes. This means that position in element containing two text nodes - * with data `foo` and `bar`, position between them has offset `3`, not `1`. - * See {@link module:engine/model/position~Position#path} for more. + * A position is represented by its {@link module:engine/model/position~Position#root} and + * a {@link module:engine/model/position~Position#path} in that root. * - * Since position in a model is represented by a {@link module:engine/model/position~Position#root position root} and - * {@link module:engine/model/position~Position#path position path} it is possible to create positions placed in non-existing elements. - * This requirement is important for operational transformation. + * You can create position instances via its constructor or the `createPosition*()` factory methods of + * {@link module:engine/model/model~Model} and {@link module:engine/model/writer~Writer}. + * + * **Note:** Position is based on offsets, not indexes. This means that a position between two text nodes + * `foo` and `bar` has offset `3`, not `1`. See {@link module:engine/model/position~Position#path} for more information. + * + * Since a position in the model is represented by a {@link module:engine/model/position~Position#root position root} and + * {@link module:engine/model/position~Position#path position path} it is possible to create positions placed in non-existing places. + * This requirement is important for operational transformation algorithms. * * Also, {@link module:engine/model/operation/operation~Operation operations} - * kept in {@link module:engine/model/document~Document#history document history} + * kept in the {@link module:engine/model/document~Document#history document history} * are storing positions (and ranges) which were correct when those operations were applied, but may not be correct - * after document got changed. + * after the document has changed. * - * When changes are applied to model, it may also happen that {@link module:engine/model/position~Position#parent position parent} + * When changes are applied to the model, it may also happen that {@link module:engine/model/position~Position#parent position parent} * will change even if position path has not changed. Keep in mind, that if a position leads to non-existing element, * {@link module:engine/model/position~Position#parent} and some other properties and methods will throw errors. * @@ -360,7 +365,7 @@ export default class Position { * @returns {module:engine/model/position~Position} Shifted position. */ getShiftedBy( shift ) { - const shifted = Position.createFromPosition( this ); + const shifted = this.clone(); const offset = shifted.offset + shift; shifted.offset = offset < 0 ? 0 : offset; @@ -448,13 +453,13 @@ export default class Position { return true; case 'before': - left = Position.createFromPosition( this ); - right = Position.createFromPosition( otherPosition ); + left = Position._createAt( this ); + right = Position._createAt( otherPosition ); break; case 'after': - left = Position.createFromPosition( otherPosition ); - right = Position.createFromPosition( this ); + left = Position._createAt( otherPosition ); + right = Position._createAt( this ); break; default: @@ -538,7 +543,7 @@ export default class Position { result = this._getTransformedByMergeOperation( operation ); break; default: - result = Position.createFromPosition( this ); + result = Position._createAt( this ); break; } @@ -612,7 +617,7 @@ export default class Position { pos = pos._getTransformedByDeletion( operation.deletionPosition, 1 ); } } else if ( this.isEqual( operation.deletionPosition ) ) { - pos = Position.createFromPosition( operation.deletionPosition ); + pos = Position._createAt( operation.deletionPosition ); } else { pos = this._getTransformedByMove( operation.deletionPosition, operation.graveyardPosition, 1 ); } @@ -630,7 +635,7 @@ export default class Position { * @returns {module:engine/model/position~Position|null} Transformed position or `null`. */ _getTransformedByDeletion( deletePosition, howMany ) { - const transformed = Position.createFromPosition( this ); + const transformed = Position._createAt( this ); // This position can't be affected if deletion was in a different root. if ( this.root != deletePosition.root ) { @@ -678,7 +683,7 @@ export default class Position { * @returns {module:engine/model/position~Position} Transformed position. */ _getTransformedByInsertion( insertPosition, howMany ) { - const transformed = Position.createFromPosition( this ); + const transformed = Position._createAt( this ); // This position can't be affected if insertion was in a different root. if ( this.root != insertPosition.root ) { @@ -721,7 +726,7 @@ export default class Position { if ( sourcePosition.isEqual( targetPosition ) ) { // If `targetPosition` is equal to `sourcePosition` this isn't really any move. Just return position as it is. - return Position.createFromPosition( this ); + return Position._createAt( this ); } // Moving a range removes nodes from their original position. We acknowledge this by proper transformation. @@ -751,9 +756,9 @@ export default class Position { * * Example: * - * let original = new Position( root, [ 2, 3, 1 ] ); - * let source = new Position( root, [ 2, 2 ] ); - * let target = new Position( otherRoot, [ 1, 1, 3 ] ); + * let original = model.createPositionFromPath( root, [ 2, 3, 1 ] ); + * let source = model.createPositionFromPath( root, [ 2, 2 ] ); + * let target = model.createPositionFromPath( otherRoot, [ 1, 1, 3 ] ); * original._getCombined( source, target ); // path is [ 1, 1, 4, 1 ], root is `otherRoot` * * Explanation: @@ -774,7 +779,7 @@ export default class Position { const i = source.path.length - 1; // The first part of a path to combined position is a path to the place where nodes were moved. - const combined = Position.createFromPosition( target ); + const combined = Position._createAt( target ); combined.stickiness = this.stickiness; // Then we have to update the rest of the path. @@ -800,6 +805,15 @@ export default class Position { }; } + /** + * Returns a new position that is equal to current position. + * + * @returns {module:engine/model/position~Position} + */ + clone() { + return new this.constructor( this.root, this.path, this.stickiness ); + } + /** * Creates position at the given location. The location can be specified as: * @@ -808,42 +822,54 @@ export default class Position { * * parent element and `'end'` (sets position at the end of that element), * * {@link module:engine/model/item~Item model item} and `'before'` or `'after'` (sets position before or after given model item). * - * This method is a shortcut to other constructors such as: + * This method is a shortcut to other factory methods such as: * - * * {@link module:engine/model/position~Position.createBefore}, - * * {@link module:engine/model/position~Position.createAfter}, - * * {@link module:engine/model/position~Position.createFromParentAndOffset}, - * * {@link module:engine/model/position~Position.createFromPosition}. + * * {@link module:engine/model/position~Position._createBefore}, + * * {@link module:engine/model/position~Position._createAfter}. * * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when * first parameter is a {@link module:engine/model/item~Item model item}. + * @protected */ - static createAt( itemOrPosition, offset ) { + static _createAt( itemOrPosition, offset ) { if ( itemOrPosition instanceof Position ) { - return this.createFromPosition( itemOrPosition ); + return new Position( itemOrPosition.root, itemOrPosition.path, itemOrPosition.stickiness ); } else { const node = itemOrPosition; if ( offset == 'end' ) { offset = node.maxOffset; } else if ( offset == 'before' ) { - return this.createBefore( node ); + return this._createBefore( node ); } else if ( offset == 'after' ) { - return this.createAfter( node ); + return this._createAfter( node ); } else if ( offset !== 0 && !offset ) { /** - * {@link module:engine/model/position~Position.createAt `Position.createAt()`} + * {@link module:engine/model/model~Model#createPositionAt `Model#createPositionAt()`} * requires the offset to be specified when the first parameter is a model item. * - * @error model-position-createAt-offset-required + * @error model-createPositionAt-offset-required */ throw new CKEditorError( - 'model-position-createAt-offset-required: ' + - 'Position.createAt() requires the offset when the first parameter is a model item.' ); + 'model-createPositionAt-offset-required: ' + + 'Model#createPositionAt() requires the offset when the first parameter is a model item.' ); } - return this.createFromParentAndOffset( node, offset ); + if ( !node.is( 'element' ) && !node.is( 'documentFragment' ) ) { + /** + * Position parent have to be a model element or model document fragment. + * + * @error model-position-parent-incorrect + */ + throw new CKEditorError( 'model-position-parent-incorrect: Position parent have to be a element or document fragment.' ); + } + + const path = node.getPath(); + + path.push( offset ); + + return new this( node.root, path ); } } @@ -852,8 +878,9 @@ export default class Position { * * @param {module:engine/model/item~Item} item Item after which the position should be placed. * @returns {module:engine/model/position~Position} + * @protected */ - static createAfter( item ) { + static _createAfter( item ) { if ( !item.parent ) { /** * You can not make a position after a root element. @@ -864,7 +891,7 @@ export default class Position { throw new CKEditorError( 'model-position-after-root: You cannot make a position after root.', { root: item } ); } - return this.createFromParentAndOffset( item.parent, item.endOffset ); + return this._createAt( item.parent, item.endOffset ); } /** @@ -872,8 +899,9 @@ export default class Position { * * @param {module:engine/model/item~Item} item Item before which the position should be placed. * @returns {module:engine/model/position~Position} + * @protected */ - static createBefore( item ) { + static _createBefore( item ) { if ( !item.parent ) { /** * You can not make a position before a root element. @@ -884,44 +912,7 @@ export default class Position { throw new CKEditorError( 'model-position-before-root: You cannot make a position before root.', { root: item } ); } - return this.createFromParentAndOffset( item.parent, item.startOffset ); - } - - /** - * Creates a new position from the parent element and an offset in that element. - * - * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} parent Position's parent. - * @param {Number} offset Position's offset. - * @returns {module:engine/model/position~Position} - */ - static createFromParentAndOffset( parent, offset ) { - if ( !parent.is( 'element' ) && !parent.is( 'documentFragment' ) ) { - /** - * Position parent have to be a model element or model document fragment. - * - * @error model-position-parent-incorrect - */ - throw new CKEditorError( 'model-position-parent-incorrect: Position parent have to be a element or document fragment.' ); - } - - const path = parent.getPath(); - - path.push( offset ); - - return new this( parent.root, path ); - } - - /** - * Creates a new position, which is equal to passed position. - * - * @param {module:engine/model/position~Position} position Position to be cloned. - * @returns {module:engine/model/position~Position} - */ - static createFromPosition( position ) { - const newPos = new this( position.root, position.path.slice() ); - newPos.stickiness = position.stickiness; - - return newPos; + return this._createAt( item.parent, item.startOffset ); } /** diff --git a/src/model/range.js b/src/model/range.js index 3ccb520b9..521145551 100644 --- a/src/model/range.js +++ b/src/model/range.js @@ -13,14 +13,18 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays'; /** - * Range class. Range is iterable. + * Represents a range in the model tree. + * + * A range is defined by its {@link module:engine/model/range~Range#start} and {@link module:engine/model/range~Range#end} + * positions. + * + * You can create range instances via its constructor or the `createRange*()` factory methods of + * {@link module:engine/model/model~Model} and {@link module:engine/model/writer~Writer}. */ export default class Range { /** * Creates a range spanning from `start` position to `end` position. * - * **Note:** Constructor creates it's own {@link module:engine/model/position~Position Position} instances basing on passed values. - * * @param {module:engine/model/position~Position} start Start position. * @param {module:engine/model/position~Position} [end] End position. If not set, range will be collapsed at `start` position. */ @@ -31,7 +35,7 @@ export default class Range { * @readonly * @member {module:engine/model/position~Position} */ - this.start = Position.createFromPosition( start ); + this.start = Position._createAt( start ); /** * End position. @@ -39,7 +43,7 @@ export default class Range { * @readonly * @member {module:engine/model/position~Position} */ - this.end = end ? Position.createFromPosition( end ) : Position.createFromPosition( start ); + this.end = end ? Position._createAt( end ) : Position._createAt( start ); // If the range is collapsed, treat in a similar way as a position and set its boundaries stickiness to 'toNone'. // In other case, make the boundaries stick to the "inside" of the range. @@ -134,7 +138,7 @@ export default class Range { * @param {module:engine/model/item~Item} item Model item to check. */ containsItem( item ) { - const pos = Position.createBefore( item ); + const pos = Position._createBefore( item ); return this.containsPosition( pos ) || this.start.isEqual( pos ); } @@ -165,16 +169,19 @@ export default class Range { * * Examples: * - * let range = new Range( new Position( root, [ 2, 7 ] ), new Position( root, [ 4, 0, 1 ] ) ); - * let otherRange = new Range( new Position( root, [ 1 ] ), new Position( root, [ 5 ] ) ); + * let range = model.createRange( + * model.createPositionFromPath( root, [ 2, 7 ] ), + * model.createPositionFromPath( root, [ 4, 0, 1 ] ) + * ); + * let otherRange = model.createRange( model.createPositionFromPath( root, [ 1 ] ), model.createPositionFromPath( root, [ 5 ] ) ); * let transformed = range.getDifference( otherRange ); * // transformed array has no ranges because `otherRange` contains `range` * - * otherRange = new Range( new Position( root, [ 1 ] ), new Position( root, [ 3 ] ) ); + * otherRange = model.createRange( model.createPositionFromPath( root, [ 1 ] ), model.createPositionFromPath( root, [ 3 ] ) ); * transformed = range.getDifference( otherRange ); * // transformed array has one range: from [ 3 ] to [ 4, 0, 1 ] * - * otherRange = new Range( new Position( root, [ 3 ] ), new Position( root, [ 4 ] ) ); + * otherRange = model.createRange( model.createPositionFromPath( root, [ 3 ] ), model.createPositionFromPath( root, [ 4 ] ) ); * transformed = range.getDifference( otherRange ); * // transformed array has two ranges: from [ 2, 7 ] to [ 3 ] and from [ 4 ] to [ 4, 0, 1 ] * @@ -200,7 +207,7 @@ export default class Range { } } else { // Ranges do not intersect, return the original range. - ranges.push( Range.createFromRange( this ) ); + ranges.push( new Range( this.start, this.end ) ); } return ranges; @@ -212,11 +219,14 @@ export default class Range { * * Examples: * - * let range = new Range( new Position( root, [ 2, 7 ] ), new Position( root, [ 4, 0, 1 ] ) ); - * let otherRange = new Range( new Position( root, [ 1 ] ), new Position( root, [ 2 ] ) ); + * let range = model.createRange( + * model.createPositionFromPath( root, [ 2, 7 ] ), + * model.createPositionFromPath( root, [ 4, 0, 1 ] ) + * ); + * let otherRange = model.createRange( model.createPositionFromPath( root, [ 1 ] ), model.createPositionFromPath( root, [ 2 ] ) ); * let transformed = range.getIntersection( otherRange ); // null - ranges have no common part * - * otherRange = new Range( new Position( root, [ 3 ] ), new Position( root, [ 5 ] ) ); + * otherRange = model.createRange( model.createPositionFromPath( root, [ 3 ] ), model.createPositionFromPath( root, [ 5 ] ) ); * transformed = range.getIntersection( otherRange ); // range from [ 3 ] to [ 4, 0, 1 ] * * @param {module:engine/model/range~Range} otherRange Range to check for intersection. @@ -291,7 +301,7 @@ export default class Range { const ranges = []; const diffAt = this.start.getCommonPath( this.end ).length; - const pos = Position.createFromPosition( this.start ); + const pos = Position._createAt( this.start ); let posParent = pos.parent; // Go up. @@ -413,7 +423,7 @@ export default class Range { return [ this._getTransformedByMergeOperation( operation ) ]; } - return [ Range.createFromRange( this ) ]; + return [ new Range( this.start, this.end ) ]; } /** @@ -424,7 +434,7 @@ export default class Range { * @returns {Array.} Range which is the result of transformation. */ getTransformedByOperations( operations ) { - const ranges = [ Range.createFromRange( this ) ]; + const ranges = [ new Range( this.start, this.end ) ]; for ( const operation of operations ) { for ( let i = 0; i < ranges.length; i++ ) { @@ -476,6 +486,15 @@ export default class Range { }; } + /** + * Returns a new range that is equal to current range. + * + * @returns {module:engine/model/range~Range} + */ + clone() { + return new this.constructor( this.start, this.end ); + } + /** * Returns a result of transforming a copy of this range by insert operation. * @@ -582,7 +601,7 @@ export default class Range { if ( operation.sourcePosition.isBefore( operation.targetPosition ) ) { // Case 1. - start = Position.createFromPosition( end ); + start = Position._createAt( end ); start.offset = 0; } else { if ( !operation.deletionPosition.isEqual( start ) ) { @@ -607,17 +626,20 @@ export default class Range { * * Examples: * - * let range = new Range( new Position( root, [ 2, 7 ] ), new Position( root, [ 4, 0, 1 ] ) ); - * let transformed = range._getTransformedByInsertion( new Position( root, [ 1 ] ), 2 ); + * let range = model.createRange( + * model.createPositionFromPath( root, [ 2, 7 ] ), + * model.createPositionFromPath( root, [ 4, 0, 1 ] ) + * ); + * let transformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 1 ] ), 2 ); * // transformed array has one range from [ 4, 7 ] to [ 6, 0, 1 ] * - * transformed = range._getTransformedByInsertion( new Position( root, [ 4, 0, 0 ] ), 4 ); + * transformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 4, 0, 0 ] ), 4 ); * // transformed array has one range from [ 2, 7 ] to [ 4, 0, 5 ] * - * transformed = range._getTransformedByInsertion( new Position( root, [ 3, 2 ] ), 4 ); + * transformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 3, 2 ] ), 4 ); * // transformed array has one range, which is equal to original range * - * transformed = range._getTransformedByInsertion( new Position( root, [ 3, 2 ] ), 4, true ); + * transformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 3, 2 ] ), 4, true ); * // transformed array has two ranges: from [ 2, 7 ] to [ 3, 2 ] and from [ 3, 6 ] to [ 4, 0, 1 ] * * @protected @@ -641,7 +663,7 @@ export default class Range { ) ]; } else { - const range = Range.createFromRange( this ); + const range = new Range( this.start, this.end ); range.start = range.start._getTransformedByInsertion( insertPosition, howMany ); range.end = range.end._getTransformedByInsertion( insertPosition, howMany ); @@ -681,7 +703,7 @@ export default class Range { //

ab

c[d

e]f

-->

ab

{
}

c[d

e]f

// // This special case is applied only if the range is to be kept together (not spread). - const moveRange = Range.createFromPositionAndShift( sourcePosition, howMany ); + const moveRange = Range._createFromPositionAndShift( sourcePosition, howMany ); const insertPosition = targetPosition._getTransformedByDeletion( sourcePosition, howMany ); if ( this.containsPosition( targetPosition ) && !spread ) { @@ -772,77 +794,39 @@ export default class Range { * Creates a new range, spreading from specified {@link module:engine/model/position~Position position} to a position moved by * given `shift`. If `shift` is a negative value, shifted position is treated as the beginning of the range. * + * @protected * @param {module:engine/model/position~Position} position Beginning of the range. * @param {Number} shift How long the range should be. * @returns {module:engine/model/range~Range} */ - static createFromPositionAndShift( position, shift ) { + static _createFromPositionAndShift( position, shift ) { const start = position; const end = position.getShiftedBy( shift ); return shift > 0 ? new this( start, end ) : new this( end, start ); } - /** - * Creates a range from given parents and offsets. - * - * @param {module:engine/model/element~Element} startElement Start position parent element. - * @param {Number} startOffset Start position offset. - * @param {module:engine/model/element~Element} endElement End position parent element. - * @param {Number} endOffset End position offset. - * @returns {module:engine/model/range~Range} - */ - static createFromParentsAndOffsets( startElement, startOffset, endElement, endOffset ) { - return new this( - Position.createFromParentAndOffset( startElement, startOffset ), - Position.createFromParentAndOffset( endElement, endOffset ) - ); - } - - /** - * Creates a new instance of `Range` which is equal to passed range. - * - * @param {module:engine/model/range~Range} range Range to clone. - * @returns {module:engine/model/range~Range} - */ - static createFromRange( range ) { - return new this( range.start, range.end ); - } - /** * Creates a range inside an {@link module:engine/model/element~Element element} which starts before the first child of * that element and ends after the last child of that element. * + * @protected * @param {module:engine/model/element~Element} element Element which is a parent for the range. * @returns {module:engine/model/range~Range} */ - static createIn( element ) { - return this.createFromParentsAndOffsets( element, 0, element, element.maxOffset ); + static _createIn( element ) { + return new this( Position._createAt( element, 0 ), Position._createAt( element, element.maxOffset ) ); } /** * Creates a range that starts before given {@link module:engine/model/item~Item model item} and ends after it. * + * @protected * @param {module:engine/model/item~Item} item * @returns {module:engine/model/range~Range} */ - static createOn( item ) { - return this.createFromPositionAndShift( Position.createBefore( item ), item.offsetSize ); - } - - /** - * Creates a collapsed range at given {@link module:engine/model/position~Position position} - * or on the given {@link module:engine/model/item~Item item}. - * - * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition - * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when - * first parameter is a {@link module:engine/model/item~Item model item}. - */ - static createCollapsedAt( itemOrPosition, offset ) { - const start = Position.createAt( itemOrPosition, offset ); - const end = Position.createFromPosition( start ); - - return new Range( start, end ); + static _createOn( item ) { + return this._createFromPositionAndShift( Position._createBefore( item ), item.offsetSize ); } /** @@ -860,17 +844,17 @@ export default class Range { * @param {Array.} ranges Ranges to combine. * @returns {module:engine/model/range~Range} Combined range. */ - static createFromRanges( ranges ) { + static _createFromRanges( ranges ) { if ( ranges.length === 0 ) { /** * At least one range has to be passed to - * {@link module:engine/model/range~Range.createFromRanges `Range.createFromRanges()`}. + * {@link module:engine/model/range~Range._createFromRanges `Range._createFromRanges()`}. * * @error range-create-from-ranges-empty-array */ throw new CKEditorError( 'range-create-from-ranges-empty-array: At least one range has to be passed.' ); } else if ( ranges.length == 1 ) { - return this.createFromRange( ranges[ 0 ] ); + return ranges[ 0 ].clone(); } // 1. Set the first range in `ranges` array as a reference range. @@ -896,7 +880,7 @@ export default class Range { if ( refIndex > 0 ) { for ( let i = refIndex - 1; true; i++ ) { if ( ranges[ i ].end.isEqual( result.start ) ) { - result.start = Position.createFromPosition( ranges[ i ].start ); + result.start = Position._createAt( ranges[ i ].start ); } else { // If ranges are not starting/ending at the same position there is no point in looking further. break; @@ -908,7 +892,7 @@ export default class Range { // Since ranges are sorted, start with the range with index that is closest to reference range index. for ( let i = refIndex + 1; i < ranges.length; i++ ) { if ( ranges[ i ].start.isEqual( result.end ) ) { - result.end = Position.createFromPosition( ranges[ i ].end ); + result.end = Position._createAt( ranges[ i ].end ); } else { // If ranges are not starting/ending at the same position there is no point in looking further. break; diff --git a/src/model/schema.js b/src/model/schema.js index 53cb22dc7..7bcb99450 100644 --- a/src/model/schema.js +++ b/src/model/schema.js @@ -547,7 +547,7 @@ export default class Schema { for ( const item of range.getItems( { shallow: true } ) ) { if ( item.is( 'element' ) ) { - yield* this._getValidRangesForRange( Range.createIn( item ), attribute ); + yield* this._getValidRangesForRange( Range._createIn( item ), attribute ); } if ( !this.checkAttribute( item, attribute ) ) { @@ -555,10 +555,10 @@ export default class Schema { yield new Range( start, end ); } - start = Position.createAfter( item ); + start = Position._createAfter( item ); } - end = Position.createAfter( item ); + end = Position._createAfter( item ); } if ( !start.isEqual( end ) ) { @@ -607,7 +607,7 @@ export default class Schema { const value = data.value; if ( value.type == type && this.isObject( value.item ) ) { - return Range.createOn( value.item ); + return Range._createOn( value.item ); } if ( this.checkChild( value.nextPosition, '$text' ) ) { @@ -667,6 +667,16 @@ export default class Schema { } } + /** + * Creates an instance of the schema context. + * + * @param {module:engine/model/schema~SchemaContextDefinition} context + * @returns {module:engine/model/schema~SchemaContext} + */ + createContext( context ) { + return new SchemaContext( context ); + } + /** * @private */ @@ -1162,7 +1172,7 @@ export class SchemaContext { * schema.checkChild( contextDefinition, childToCheck ); * * // Also check in [ rootElement, blockQuoteElement, paragraphElement ]. - * schema.checkChild( Position.createAt( paragraphElement, 0 ), 'foo' ); + * schema.checkChild( model.createPositionAt( paragraphElement, 0 ), 'foo' ); * * // Check in [ rootElement, paragraphElement ]. * schema.checkChild( [ rootElement, paragraphElement ], 'foo' ); diff --git a/src/model/selection.js b/src/model/selection.js index d800538a1..a2e319ed5 100644 --- a/src/model/selection.js +++ b/src/model/selection.js @@ -36,46 +36,46 @@ export default class Selection { * or creates an empty selection if no arguments were passed. * * // Creates empty selection without ranges. - * const selection = new Selection(); + * const selection = writer.createSelection(); * * // Creates selection at the given range. - * const range = new Range( start, end ); - * const selection = new Selection( range ); + * const range = writer.createRange( start, end ); + * const selection = writer.createSelection( range ); * * // Creates selection at the given ranges - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; - * const selection = new Selection( ranges ); + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; + * const selection = writer.createSelection( ranges ); * * // Creates selection from the other selection. * // Note: It doesn't copies selection attributes. - * const otherSelection = new Selection(); - * const selection = new Selection( otherSelection ); + * const otherSelection = writer.createSelection(); + * const selection = writer.createSelection( otherSelection ); * * // Creates selection from the given document selection. * // Note: It doesn't copies selection attributes. - * const documentSelection = new DocumentSelection( doc ); - * const selection = new Selection( documentSelection ); + * const documentSelection = model.document.selection; + * const selection = writer.createSelection( documentSelection ); * * // Creates selection at the given position. - * const position = new Position( root, path ); - * const selection = new Selection( position ); + * const position = writer.createPositionFromPath( root, path ); + * const selection = writer.createSelection( position ); * * // Creates selection at the given offset in the given element. * const paragraph = writer.createElement( 'paragraph' ); - * const selection = new Selection( paragraph, offset ); + * const selection = writer.createSelection( paragraph, offset ); * * // Creates a range inside an {@link module:engine/model/element~Element element} which starts before the * // first child of that element and ends after the last child of that element. - * const selection = new Selection( paragraph, 'in' ); + * const selection = writer.createSelection( paragraph, 'in' ); * * // Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends * // just after the item. - * const selection = new Selection( paragraph, 'on' ); + * const selection = writer.createSelection( paragraph, 'on' ); * * Selection's constructor allow passing additional options (`'backward'`) as the last argument. * * // Creates backward selection. - * const selection = new Selection( range, { backward: true } ); + * const selection = writer.createSelection( range, { backward: true } ); * * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection| * module:engine/model/position~Position|module:engine/model/element~Element| @@ -242,7 +242,7 @@ export default class Selection { */ * getRanges() { for ( const range of this._ranges ) { - yield Range.createFromRange( range ); + yield new Range( range.start, range.end ); } } @@ -265,7 +265,7 @@ export default class Selection { } } - return first ? Range.createFromRange( first ) : null; + return first ? new Range( first.start, first.end ) : null; } /** @@ -287,7 +287,7 @@ export default class Selection { } } - return last ? Range.createFromRange( last ) : null; + return last ? new Range( last.start, last.end ) : null; } /** @@ -302,7 +302,7 @@ export default class Selection { getFirstPosition() { const first = this.getFirstRange(); - return first ? Position.createFromPosition( first.start ) : null; + return first ? first.start.clone() : null; } /** @@ -317,7 +317,7 @@ export default class Selection { getLastPosition() { const lastRange = this.getLastRange(); - return lastRange ? Position.createFromPosition( lastRange.end ) : null; + return lastRange ? lastRange.end.clone() : null; } /** @@ -330,16 +330,16 @@ export default class Selection { * selection.setTo( null ); * * // Sets selection to the given range. - * const range = new Range( start, end ); + * const range = writer.createRange( start, end ); * selection.setTo( range ); * * // Sets selection to given ranges. - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; * selection.setTo( ranges ); * * // Sets selection to other selection. * // Note: It doesn't copies selection attributes. - * const otherSelection = new Selection(); + * const otherSelection = writer.createSelection(); * selection.setTo( otherSelection ); * * // Sets selection to the given document selection. @@ -348,7 +348,7 @@ export default class Selection { * selection.setTo( documentSelection ); * * // Sets collapsed selection at the given position. - * const position = new Position( root, path ); + * const position = writer.createPositionFromPath( root, path ); * selection.setTo( position ); * * // Sets collapsed selection at the position of the given node and an offset. @@ -366,7 +366,7 @@ export default class Selection { * `Selection#setTo()`' method allow passing additional options (`backward`) as the last argument. * * // Sets backward selection. - * const selection = new Selection( range, { backward: true } ); + * const selection = writer.createSelection( range, { backward: true } ); * * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection| * module:engine/model/position~Position|module:engine/model/node~Node| @@ -393,11 +393,11 @@ export default class Selection { let range; if ( placeOrOffset == 'in' ) { - range = Range.createIn( selectable ); + range = Range._createIn( selectable ); } else if ( placeOrOffset == 'on' ) { - range = Range.createOn( selectable ); + range = Range._createOn( selectable ); } else if ( placeOrOffset !== undefined ) { - range = Range.createCollapsedAt( selectable, placeOrOffset ); + range = new Range( Position._createAt( selectable, placeOrOffset ) ); } else { /** * selection.setTo requires the second parameter when the first parameter is a node. @@ -481,7 +481,8 @@ export default class Selection { /** * Moves {@link module:engine/model/selection~Selection#focus} to the specified location. * - * The location can be specified in the same form as {@link module:engine/model/position~Position.createAt} parameters. + * The location can be specified in the same form as + * {@link module:engine/model/writer~Writer#createPositionAt writer.createPositionAt()} parameters. * * @fires change:range * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition @@ -500,7 +501,7 @@ export default class Selection { ); } - const newFocus = Position.createAt( itemOrPosition, offset ); + const newFocus = Position._createAt( itemOrPosition, offset ); if ( newFocus.compareWith( this.focus ) == 'same' ) { return; @@ -665,7 +666,7 @@ export default class Selection { const endBlock = getParentBlock( range.end, visited ); // #984. Don't return the end block if the range ends right at its beginning. - if ( endBlock && !range.end.isTouching( Position.createAt( endBlock, 0 ) ) ) { + if ( endBlock && !range.end.isTouching( Position._createAt( endBlock, 0 ) ) ) { yield endBlock; } } @@ -683,8 +684,8 @@ export default class Selection { * @returns {Boolean} */ containsEntireContent( element = this.anchor.root ) { - const limitStartPosition = Position.createAt( element, 0 ); - const limitEndPosition = Position.createAt( element, 'end' ); + const limitStartPosition = Position._createAt( element, 0 ); + const limitEndPosition = Position._createAt( element, 'end' ); return limitStartPosition.isTouching( this.getFirstPosition() ) && limitEndPosition.isTouching( this.getLastPosition() ); @@ -699,7 +700,7 @@ export default class Selection { */ _pushRange( range ) { this._checkRange( range ); - this._ranges.push( Range.createFromRange( range ) ); + this._ranges.push( new Range( range.start, range.end ) ); } /** diff --git a/src/model/treewalker.js b/src/model/treewalker.js index 6c9049daa..58a5245b7 100644 --- a/src/model/treewalker.js +++ b/src/model/treewalker.js @@ -85,9 +85,9 @@ export default class TreeWalker { * @member {module:engine/model/position~Position} module:engine/model/treewalker~TreeWalker#position */ if ( options.startPosition ) { - this.position = Position.createFromPosition( options.startPosition ); + this.position = options.startPosition.clone(); } else { - this.position = Position.createFromPosition( this.boundaries[ this.direction == 'backward' ? 'end' : 'start' ] ); + this.position = Position._createAt( this.boundaries[ this.direction == 'backward' ? 'end' : 'start' ] ); } // Reset position stickiness in case it was set to other value, as the stickiness is kept after cloning. @@ -208,7 +208,7 @@ export default class TreeWalker { */ _next() { const previousPosition = this.position; - const position = Position.createFromPosition( this.position ); + const position = this.position.clone(); const parent = this._visitedParent; // We are at the end of the root. @@ -282,7 +282,7 @@ export default class TreeWalker { */ _previous() { const previousPosition = this.position; - const position = Position.createFromPosition( this.position ); + const position = this.position.clone(); const parent = this._visitedParent; // We are at the beginning of the root. @@ -379,10 +379,7 @@ function formatReturnValue( type, item, previousPosition, nextPosition, length ) * @property {module:engine/model/item~Item} item Item between old and new positions of {@link module:engine/model/treewalker~TreeWalker}. * @property {module:engine/model/position~Position} previousPosition Previous position of the iterator. * * Forward iteration: For `'elementEnd'` it is the last position inside the element. For all other types it is the - * position before the item. Note that it is more efficient to use this position then calculate the position before - * the node using {@link module:engine/model/position~Position.createBefore}. It is also more efficient to get the - * position after node by shifting `previousPosition` by `length`, using {@link module:engine/model/position~Position#getShiftedBy}, - * then calculate the position using {@link module:engine/model/position~Position.createAfter}. + * position before the item. * * Backward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is * the position after item. * @property {module:engine/model/position~Position} nextPosition Next position of the iterator. @@ -391,7 +388,7 @@ function formatReturnValue( type, item, previousPosition, nextPosition, length ) * * Backward iteration: For `'elementEnd'` it is last position inside element. For all other types it is the position * before the item. * @property {Number} [length] Length of the item. For `'elementStart'` and `'character'` it is 1. For `'text'` it is - * the length of the text. For `'elementEnd'` it is undefined. + * the length of the text. For `'elementEnd'` it is `undefined`. */ /** diff --git a/src/model/utils/deletecontent.js b/src/model/utils/deletecontent.js index 2828f8365..170a8b7b9 100644 --- a/src/model/utils/deletecontent.js +++ b/src/model/utils/deletecontent.js @@ -8,7 +8,6 @@ */ import LivePosition from '../liveposition'; -import Position from '../position'; import Range from '../range'; import DocumentSelection from '../documentselection'; @@ -62,8 +61,7 @@ export default function deleteContent( model, selection, options = {} ) { const selRange = selection.getFirstRange(); const startPos = selRange.start; - const endPos = LivePosition.createFromPosition( selRange.end ); - endPos.stickiness = 'toNext'; + const endPos = LivePosition.fromPosition( selRange.end, 'toNext' ); // 2. Remove the content if there is any. if ( !selRange.start.isTouching( selRange.end ) ) { @@ -134,8 +132,8 @@ function mergeBranches( writer, startPos, endPos ) { // x[]{}y // will become: // xy[]{} - startPos = Position.createAfter( startParent ); - endPos = Position.createBefore( endParent ); + startPos = writer.createPositionAfter( startParent ); + endPos = writer.createPositionBefore( endParent ); if ( !endPos.isEqual( startPos ) ) { // In this case, before we merge, we need to move `endParent` to the `startPos`: @@ -158,7 +156,7 @@ function mergeBranches( writer, startPos, endPos ) { while ( endPos.parent.isEmpty ) { const parentToRemove = endPos.parent; - endPos = Position.createBefore( parentToRemove ); + endPos = writer.createPositionBefore( parentToRemove ); writer.remove( parentToRemove ); } @@ -207,8 +205,8 @@ function insertParagraph( writer, position, selection ) { function replaceEntireContentWithParagraph( writer, selection ) { const limitElement = writer.model.schema.getLimitElement( selection ); - writer.remove( Range.createIn( limitElement ) ); - insertParagraph( writer, Position.createAt( limitElement, 0 ), selection ); + writer.remove( writer.createRangeIn( limitElement ) ); + insertParagraph( writer, writer.createPositionAt( limitElement, 0 ), selection ); } // We want to replace the entire content with a paragraph when: diff --git a/src/model/utils/getselectedcontent.js b/src/model/utils/getselectedcontent.js index 037db1a55..876cb75c7 100644 --- a/src/model/utils/getselectedcontent.js +++ b/src/model/utils/getselectedcontent.js @@ -7,9 +7,6 @@ * @module engine/model/utils/getselectedcontent */ -import Range from '../range'; -import Position from '../position'; - /** * Gets a clone of the selected content. * @@ -63,9 +60,9 @@ export default function getSelectedContent( model, selection ) { // The original range is flat, so take it. flatSubtreeRange = range; } else { - flatSubtreeRange = Range.createFromParentsAndOffsets( - commonParent, range.start.path[ commonPath.length ], - commonParent, range.end.path[ commonPath.length ] + 1 + flatSubtreeRange = writer.createRange( + writer.createPositionAt( commonParent, range.start.path[ commonPath.length ] ), + writer.createPositionAt( commonParent, range.end.path[ commonPath.length ] + 1 ) ); } @@ -97,10 +94,10 @@ export default function getSelectedContent( model, selection ) { // [

y

fir]st

se[cond

] if ( flatSubtreeRange != range ) { // Find the position of the original range in the cloned fragment. - const newRange = range._getTransformedByMove( flatSubtreeRange.start, Position.createAt( frag, 0 ), howMany )[ 0 ]; + const newRange = range._getTransformedByMove( flatSubtreeRange.start, writer.createPositionAt( frag, 0 ), howMany )[ 0 ]; - const leftExcessRange = new Range( Position.createAt( frag, 0 ), newRange.start ); - const rightExcessRange = new Range( newRange.end, Position.createAt( frag, 'end' ) ); + const leftExcessRange = writer.createRange( writer.createPositionAt( frag, 0 ), newRange.start ); + const rightExcessRange = writer.createRange( newRange.end, writer.createPositionAt( frag, 'end' ) ); removeRangeContent( rightExcessRange, writer ); removeRangeContent( leftExcessRange, writer ); @@ -118,7 +115,7 @@ function removeRangeContent( range, writer ) { Array.from( range.getItems( { direction: 'backward' } ) ) // We should better store ranges because text proxies will lose integrity // with the text nodes when we'll start removing content. - .map( item => Range.createOn( item ) ) + .map( item => writer.createRangeOn( item ) ) // Filter only these items which are fully contained in the passed range. // // E.g. for the following range: [

y

fir]st @@ -143,7 +140,7 @@ function removeRangeContent( range, writer ) { let parent = parentToCheck; while ( parent.parent && parent.isEmpty ) { - const removeRange = Range.createOn( parent ); + const removeRange = writer.createRangeOn( parent ); parent = parent.parent; diff --git a/src/model/utils/insertcontent.js b/src/model/utils/insertcontent.js index b9db0e9dd..aea30ee02 100644 --- a/src/model/utils/insertcontent.js +++ b/src/model/utils/insertcontent.js @@ -44,7 +44,7 @@ export default function insertContent( model, content, selectable, placeOrOffset } else if ( selectable instanceof Selection || selectable instanceof DocumentSelection ) { selection = selectable; } else { - selection = new Selection( selectable, placeOrOffset ); + selection = writer.createSelection( selectable, placeOrOffset ); } if ( !selection.isCollapsed ) { @@ -174,7 +174,7 @@ class Insertion { */ getSelectionRange() { if ( this.nodeToSelect ) { - return Range.createOn( this.nodeToSelect ); + return Range._createOn( this.nodeToSelect ); } return this.model.schema.getNearestSelectionRange( this.position ); @@ -276,12 +276,11 @@ class Insertion { return; } - const livePos = LivePosition.createFromPosition( this.position ); - livePos.stickiness = 'toNext'; + const livePos = LivePosition.fromPosition( this.position, 'toNext' ); this.writer.insert( node, this.position ); - this.position = Position.createFromPosition( livePos ); + this.position = livePos.toPosition(); livePos.detach(); // The last inserted object should be selected because we can't put a collapsed selection after it. @@ -306,19 +305,19 @@ class Insertion { const mergeLeft = this._canMergeLeft( node, context ); const mergeRight = this._canMergeRight( node, context ); - const mergePosLeft = LivePosition.createBefore( node ); + const mergePosLeft = LivePosition._createBefore( node ); mergePosLeft.stickiness = 'toNext'; - const mergePosRight = LivePosition.createAfter( node ); + const mergePosRight = LivePosition._createAfter( node ); mergePosRight.stickiness = 'toNext'; if ( mergeLeft ) { - const position = LivePosition.createFromPosition( this.position ); - position.stickiness = 'toNext'; + const livePosition = LivePosition.fromPosition( this.position ); + livePosition.stickiness = 'toNext'; this.writer.merge( mergePosLeft ); - this.position = Position.createFromPosition( position ); - position.detach(); + this.position = livePosition.toPosition(); + livePosition.detach(); } if ( mergeRight ) { @@ -332,16 +331,16 @@ class Insertion { // Move the position to the previous node, so it isn't moved to the graveyard on merge. //

x

[]

y

=>

x[]

y

- this.position = Position.createAt( mergePosRight.nodeBefore, 'end' ); + this.position = Position._createAt( mergePosRight.nodeBefore, 'end' ); // OK:

xx[]

+

yy

=>

xx[]yy

(when sticks to previous) // NOK:

xx[]

+

yy

=>

xxyy[]

(when sticks to next) - const position = new LivePosition( this.position.root, this.position.path, 'toPrevious' ); + const livePosition = new LivePosition( this.position.root, this.position.path, 'toPrevious' ); this.writer.merge( mergePosRight ); - this.position = Position.createFromPosition( position ); - position.detach(); + this.position = livePosition.toPosition(); + livePosition.detach(); } if ( mergeLeft || mergeRight ) { @@ -428,7 +427,7 @@ class Insertion { if ( this.position.isAtStart ) { const parent = this.position.parent; - this.position = Position.createBefore( parent ); + this.position = this.writer.createPositionBefore( parent ); // Special case – parent is empty (

^

) so isAtStart == isAtEnd == true. // We can remove the element after moving selection out of it. @@ -436,9 +435,9 @@ class Insertion { this.writer.remove( parent ); } } else if ( this.position.isAtEnd ) { - this.position = Position.createAfter( this.position.parent ); + this.position = this.writer.createPositionAfter( this.position.parent ); } else { - const tempPos = Position.createAfter( this.position.parent ); + const tempPos = this.writer.createPositionAfter( this.position.parent ); this.writer.split( this.position ); diff --git a/src/model/utils/modifyselection.js b/src/model/utils/modifyselection.js index e5030ca84..95f320b95 100644 --- a/src/model/utils/modifyselection.js +++ b/src/model/utils/modifyselection.js @@ -106,7 +106,7 @@ function tryExtendingTo( data, value ) { if ( value.type == ( data.isForward ? 'elementStart' : 'elementEnd' ) ) { // If it's an object, we can select it now. if ( data.schema.isObject( value.item ) ) { - return Position.createAt( value.item, data.isForward ? 'after' : 'before' ); + return Position._createAt( value.item, data.isForward ? 'after' : 'before' ); } // If text allowed on this position, extend to this place. @@ -195,7 +195,7 @@ function getCorrectWordBreakPosition( walker, isForward ) { function getSearchRange( start, isForward ) { const root = start.root; - const searchEnd = Position.createAt( root, isForward ? 'end' : 0 ); + const searchEnd = Position._createAt( root, isForward ? 'end' : 0 ); if ( isForward ) { return new Range( start, searchEnd ); diff --git a/src/model/utils/selection-post-fixer.js b/src/model/utils/selection-post-fixer.js index bd651509d..abfa23fea 100644 --- a/src/model/utils/selection-post-fixer.js +++ b/src/model/utils/selection-post-fixer.js @@ -149,7 +149,7 @@ function tryFixingCollapsedRange( range, schema ) { // Check single node selection (happens in tables). if ( fixedPosition.nodeAfter && schema.isLimit( fixedPosition.nodeAfter ) ) { - return new Range( fixedPosition, Position.createAfter( fixedPosition.nodeAfter ) ); + return new Range( fixedPosition, Position._createAfter( fixedPosition.nodeAfter ) ); } return new Range( fixedPosition ); @@ -199,8 +199,8 @@ function tryFixingNonCollapsedRage( range, schema ) { if ( isStartInLimit || isEndInLimit ) { // Although we've already found limit element on start/end positions we must find the outer-most limit element. // as limit elements might be nested directly inside (ie table > tableRow > tableCell). - const startPosition = Position.createAt( startLimitElement, 0 ); - const endPosition = Position.createAt( endLimitElement, 0 ); + const startPosition = Position._createAt( startLimitElement, 0 ); + const endPosition = Position._createAt( endLimitElement, 0 ); const fixedStart = isStartInLimit ? expandSelectionOnIsLimitNode( startPosition, schema, 'start' ) : start; const fixedEnd = isEndInLimit ? expandSelectionOnIsLimitNode( endPosition, schema, 'end' ) : end; @@ -229,7 +229,7 @@ function expandSelectionOnIsLimitNode( position, schema, expandToDirection ) { } // Depending on direction of expanding selection return position before or after found node. - return expandToDirection === 'start' ? Position.createBefore( node ) : Position.createAfter( node ); + return expandToDirection === 'start' ? Position._createBefore( node ) : Position._createAfter( node ); } // Checks whether both range ends are placed around non-limit elements. diff --git a/src/model/writer.js b/src/model/writer.js index 9717e72d9..b17684103 100644 --- a/src/model/writer.js +++ b/src/model/writer.js @@ -137,7 +137,7 @@ export default class Writer { * const paragraph = writer.createElement( 'paragraph' ); * writer.insert( paragraph, anotherParagraph, 'after' ); * - * These parameters works the same way as {@link module:engine/model/position~Position.createAt `Position.createAt()`}. + * These parameters works the same way as {@link #createPositionAt `writer.createPositionAt()`}. * * Note that if the item already has parent it will be removed from the previous parent. * @@ -159,14 +159,14 @@ export default class Writer { insert( item, itemOrPosition, offset = 0 ) { this._assertWriterUsedCorrectly(); - const position = Position.createAt( itemOrPosition, offset ); + const position = Position._createAt( itemOrPosition, offset ); // If item has a parent already. if ( item.parent ) { // We need to check if item is going to be inserted within the same document. if ( isSameTree( item.root, position.root ) ) { // If it's we just need to move it. - this.move( Range.createOn( item ), position ); + this.move( Range._createOn( item ), position ); return; } @@ -198,7 +198,7 @@ export default class Writer { if ( item instanceof DocumentFragment ) { for ( const [ markerName, markerRange ] of item.markers ) { // We need to migrate marker range from DocumentFragment to Document. - const rangeRootPosition = Position.createAt( markerRange.root, 0 ); + const rangeRootPosition = Position._createAt( markerRange.root, 0 ); const range = new Range( markerRange.start._getCombined( rangeRootPosition, position ), markerRange.end._getCombined( rangeRootPosition, position ) @@ -225,7 +225,7 @@ export default class Writer { * // Inserts 'foo' after an image: * writer.insertText( 'foo', image, 'after' ); * - * These parameters work in the same way as {@link module:engine/model/position~Position.createAt `Position.createAt()`}. + * These parameters work in the same way as {@link #createPositionAt `writer.createPositionAt()`}. * * @param {String} data Text data. * @param {Object} [attributes] Text attributes. @@ -257,7 +257,7 @@ export default class Writer { * // Inserts after an image: * writer.insertElement( 'paragraph', image, 'after' ); * - * These parameters works the same way as {@link module:engine/model/position~Position.createAt `Position.createAt()`}. + * These parameters works the same way as {@link #createPositionAt `writer.createPositionAt()`}. * * @param {String} name Name of the element. * @param {Object} [attributes] Elements attributes. @@ -431,7 +431,7 @@ export default class Writer { * // Moves all items in the range to a position after an image: * writer.move( sourceRange, image, 'after' ); * - * These parameters works the same way as {@link module:engine/model/position~Position.createAt `Position.createAt()`}. + * These parameters works the same way as {@link #createPositionAt `writer.createPositionAt()`}. * * Note that items can be moved only within the same tree. It means that you can move items within the same root * (element or document fragment) or between {@link module:engine/model/document~Document#roots documents roots}, @@ -464,7 +464,7 @@ export default class Writer { throw new CKEditorError( 'writer-move-range-not-flat: Range to move is not flat.' ); } - const position = Position.createAt( itemOrPosition, offset ); + const position = Position._createAt( itemOrPosition, offset ); if ( !isSameTree( range.root, position.root ) ) { /** @@ -501,7 +501,7 @@ export default class Writer { } else { const howMany = itemOrRange.is( 'text' ) ? itemOrRange.offsetSize : 1; - applyRemoveOperation( Position.createBefore( itemOrRange ), howMany, this.batch, this.model ); + applyRemoveOperation( Position._createBefore( itemOrRange ), howMany, this.batch, this.model ); } } @@ -544,6 +544,97 @@ export default class Writer { } } + /** + * Shortcut for {@link module:engine/model/model~Model#createPositionFromPath `Model#createPositionFromPath()`}. + * + * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} root Root of the position. + * @param {Array.} path Position path. See {@link module:engine/model/position~Position#path}. + * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness. + * See {@link module:engine/model/position~PositionStickiness}. + * @returns {module:engine/model/position~Position} + */ + createPositionFromPath( root, path, stickiness ) { + return this.model.createPositionFromPath( root, path, stickiness ); + } + + /** + * Shortcut for {@link module:engine/model/model~Model#createPositionAt `Model#createPositionAt()`}. + * + * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition + * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when + * first parameter is a {@link module:engine/model/item~Item model item}. + * @returns {module:engine/model/position~Position} + */ + createPositionAt( itemOrPosition, offset ) { + return this.model.createPositionAt( itemOrPosition, offset ); + } + + /** + * Shortcut for {@link module:engine/model/model~Model#createPositionAfter `Model#createPositionAfter()`}. + * + * @param {module:engine/model/item~Item} item Item after which the position should be placed. + * @returns {module:engine/model/position~Position} + */ + createPositionAfter( item ) { + return this.model.createPositionAfter( item ); + } + + /** + * Shortcut for {@link module:engine/model/model~Model#createPositionBefore `Model#createPositionBefore()`}. + * + * @param {module:engine/model/item~Item} item Item after which the position should be placed. + * @returns {module:engine/model/position~Position} + */ + createPositionBefore( item ) { + return this.model.createPositionBefore( item ); + } + + /** + * Shortcut for {@link module:engine/model/model~Model#createRange `Model#createRange()`}. + * + * @param {module:engine/model/position~Position} start Start position. + * @param {module:engine/model/position~Position} [end] End position. If not set, range will be collapsed at `start` position. + * @returns {module:engine/model/range~Range} + */ + createRange( start, end ) { + return this.model.createRange( start, end ); + } + + /** + * Shortcut for {@link module:engine/model/model~Model#createRangeIn `Model#createRangeIn()`}. + * + * @param {module:engine/model/element~Element} element Element which is a parent for the range. + * @returns {module:engine/model/range~Range} + */ + createRangeIn( element ) { + return this.model.createRangeIn( element ); + } + + /** + * Shortcut for {@link module:engine/model/model~Model#createRangeOn `Model#createRangeOn()`}. + * + * @param {module:engine/model/element~Element} element Element which is a parent for the range. + * @returns {module:engine/model/range~Range} + */ + createRangeOn( element ) { + return this.model.createRangeOn( element ); + } + + /** + * Shortcut for {@link module:engine/model/model~Model#createSelection `Model#createSelection()`}. + * + * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection| + * module:engine/model/position~Position|module:engine/model/element~Element| + * Iterable.|module:engine/model/range~Range|null} selectable + * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection. + * @param {Object} [options] + * @param {Boolean} [options.backward] Sets this selection instance to be backward. + * @returns {module:engine/model/selection~Selection} + */ + createSelection( selectable, placeOrOffset, options ) { + return this.model.createSelection( selectable, placeOrOffset, options ); + } + /** * Performs merge action in a detached tree. * @@ -554,7 +645,7 @@ export default class Writer { const nodeBefore = position.nodeBefore; const nodeAfter = position.nodeAfter; - this.move( Range.createIn( nodeAfter ), Position.createAt( nodeBefore, 'end' ) ); + this.move( Range._createIn( nodeAfter ), Position._createAt( nodeBefore, 'end' ) ); this.remove( nodeAfter ); } @@ -565,8 +656,8 @@ export default class Writer { * @param {module:engine/model/position~Position} position Position between merged elements. */ _merge( position ) { - const targetPosition = Position.createAt( position.nodeBefore, 'end' ); - const sourcePosition = Position.createAt( position.nodeAfter, 0 ); + const targetPosition = Position._createAt( position.nodeBefore, 'end' ); + const sourcePosition = Position._createAt( position.nodeAfter, 0 ); const graveyard = position.root.document.graveyard; const graveyardPosition = new Position( graveyard, [ 0 ] ); @@ -600,7 +691,7 @@ export default class Writer { } const version = element.root.document ? element.root.document.version : null; - const renameOperation = new RenameOperation( Position.createBefore( element ), element.name, newName, version ); + const renameOperation = new RenameOperation( Position._createBefore( element ), element.name, newName, version ); this.batch.addOperation( renameOperation ); this.model.applyOperation( renameOperation ); @@ -662,13 +753,13 @@ export default class Writer { firstCopyElement = position.parent.nextSibling; } - position = Position.createAfter( position.parent ); + position = this.createPositionAfter( position.parent ); splitElement = position.parent; } while ( splitElement !== limitElement ); return { position, - range: new Range( Position.createAt( firstSplitElement, 'end' ), Position.createAt( firstCopyElement, 0 ) ) + range: new Range( Position._createAt( firstSplitElement, 'end' ), Position._createAt( firstCopyElement, 0 ) ) }; } @@ -723,7 +814,7 @@ export default class Writer { const move = new MoveOperation( range.start.getShiftedBy( 1 ), range.end.offset - range.start.offset, - Position.createAt( element, 0 ), + Position._createAt( element, 0 ), version === null ? null : version + 1 ); @@ -749,7 +840,7 @@ export default class Writer { throw new CKEditorError( 'writer-unwrap-element-no-parent: Trying to unwrap an element which has no parent.' ); } - this.move( Range.createIn( element ), Position.createAfter( element ) ); + this.move( Range._createIn( element ), this.createPositionAfter( element ) ); this.remove( element ); } @@ -976,29 +1067,33 @@ export default class Writer { } /** - * Sets this selection's ranges and direction to the specified location based on the given - * {@link module:engine/model/selection~Selection selection}, {@link module:engine/model/position~Position position}, - * {@link module:engine/model/node~Node node}, {@link module:engine/model/position~Position position}, - * {@link module:engine/model/range~Range range}, an iterable of {@link module:engine/model/range~Range ranges} or null. + * Sets the document's selection (ranges and direction) to the specified location based on: + * + * * the given {@link module:engine/model/selection~Selection selection}, + * * or the given {@link module:engine/model/position~Position position}, + * * or the given {@link module:engine/model/range~Range range}, + * * or the given iterable of {@link module:engine/model/range~Range ranges}, + * * or the given {@link module:engine/model/node~Node node}, + * * or `null`. * * // Sets selection to the given range. - * const range = new Range( start, end ); + * const range = writer.createRange( start, end ); * writer.setSelection( range ); * * // Sets selection to given ranges. - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; * writer.setSelection( range ); * * // Sets selection to other selection. - * const otherSelection = new Selection(); + * const otherSelection = writer.createSelection(); * writer.setSelection( otherSelection ); * * // Sets selection to the given document selection. - * const documentSelection = new DocumentSelection( doc ); + * const documentSelection = model.document.selection; * writer.setSelection( documentSelection ); * * // Sets collapsed selection at the given position. - * const position = new Position( root, path ); + * const position = writer.createPosition( root, path ); * writer.setSelection( position ); * * // Sets collapsed selection at the position of the given node and an offset. @@ -1040,7 +1135,7 @@ export default class Writer { * Moves {@link module:engine/model/documentselection~DocumentSelection#focus} to the specified location. * * The location can be specified in the same form as - * {@link module:engine/model/position~Position.createAt `Position.createAt()`} parameters. + * {@link #createPositionAt `writer.createPositionAt()`} parameters. * * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition * @param {Number|'end'|'before'|'after'} [offset=0] Offset or one of the flags. Used only when @@ -1286,7 +1381,7 @@ function setAttributeOnItem( writer, key, value, item ) { operation = new RootAttributeOperation( item, key, previousValue, value, version ); } else { - range = new Range( Position.createBefore( item ), Position.createAfter( item ) ); + range = new Range( Position._createBefore( item ), writer.createPositionAfter( item ) ); const version = range.root.document ? doc.version : null; diff --git a/src/view/documentselection.js b/src/view/documentselection.js index 9497949d9..8f3431068 100644 --- a/src/view/documentselection.js +++ b/src/view/documentselection.js @@ -12,20 +12,14 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix'; import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin'; /** - * Class representing document selection in tree view. It's instance is stored at - * {@link module:engine/view/document~Document#selection}. It is similar to {@link module:engine/view/selection~Selection} but - * it has read-only API and can be modified only by writer obtained from {@link module:engine/view/view~View#change} method. + * Class representing the document selection in the view. * - * Selection can consist of {@link module:engine/view/range~Range ranges}. - * Selection's ranges can be obtained via {@link module:engine/view/documentselection~DocumentSelection#getRanges getRanges}, - * {@link module:engine/view/documentselection~DocumentSelection#getFirstRange getFirstRange} - * and {@link module:engine/view/documentselection~DocumentSelection#getLastRange getLastRange} - * methods, which return copies of ranges stored inside selection. Modifications made on these copies will not change - * selection's state. Similar situation occurs when getting {@link module:engine/view/documentselection~DocumentSelection#anchor anchor}, - * {@link module:engine/view/documentselection~DocumentSelection#focus focus}, - * {@link module:engine/view/documentselection~DocumentSelection#getFirstPosition first} and - * {@link module:engine/view/documentselection~DocumentSelection#getLastPosition last} positions - all will return - * copies of requested positions. + * Its instance is available in {@link module:engine/view/document~Document#selection `Document#selection`}. + * + * It is similar to {@link module:engine/view/selection~Selection} but + * it has a read-only API and can be modified only by the writer available in + * the {@link module:engine/view/view~View#change `View#change()`} block + * (so via {@link module:engine/view/downcastwriter~DowncastWriter#setSelection `DowncastWriter#setSelection()`}). */ export default class DocumentSelection { /** @@ -35,19 +29,19 @@ export default class DocumentSelection { * const selection = new DocumentSelection(); * * // Creates selection at the given range. - * const range = new Range( start, end ); + * const range = writer.createRange( start, end ); * const selection = new DocumentSelection( range ); * * // Creates selection at the given ranges - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( start2, end2 ) ]; * const selection = new DocumentSelection( ranges ); * * // Creates selection from the other selection. - * const otherSelection = new Selection(); + * const otherSelection = writer.createSelection(); * const selection = new DocumentSelection( otherSelection ); * * // Creates selection at the given position. - * const position = new Position( root, path ); + * const position = writer.createPositionAt( root, offset ); * const selection = new DocumentSelection( position ); * * // Creates collapsed selection at the position of given item and offset. @@ -290,19 +284,19 @@ export default class DocumentSelection { * an iterable of {@link module:engine/view/range~Range ranges} or null. * * // Sets selection to the given range. - * const range = new Range( start, end ); + * const range = writer.createRange( start, end ); * documentSelection._setTo( range ); * * // Sets selection to given ranges. - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( start2, end2 ) ]; * documentSelection._setTo( range ); * * // Sets selection to the other selection. - * const otherSelection = new Selection(); + * const otherSelection = writer.createSelection(); * documentSelection._setTo( otherSelection ); * * // Sets collapsed selection at the given position. - * const position = new Position( root, path ); + * const position = writer.createPositionAt( root, offset ); * documentSelection._setTo( position ); * * // Sets collapsed selection at the position of given item and offset. @@ -352,7 +346,8 @@ export default class DocumentSelection { /** * Moves {@link #focus} to the specified location. * - * The location can be specified in the same form as {@link module:engine/view/position~Position.createAt} parameters. + * The location can be specified in the same form as {@link module:engine/view/view~View#createPositionAt view.createPositionAt()} + * parameters. * * @protected * @fires change diff --git a/src/view/domconverter.js b/src/view/domconverter.js index d30e59a76..160f16da8 100644 --- a/src/view/domconverter.js +++ b/src/view/domconverter.js @@ -534,7 +534,7 @@ export default class DomConverter { const viewElement = this.mapDomToView( domParent ); if ( viewElement && viewElement.is( 'uiElement' ) ) { - return ViewPosition.createBefore( viewElement ); + return ViewPosition._createBefore( viewElement ); } if ( isText( domParent ) ) { @@ -1066,7 +1066,7 @@ export default class DomConverter { */ _getTouchingViewTextNode( node, getNext ) { const treeWalker = new ViewTreeWalker( { - startPosition: getNext ? ViewPosition.createAfter( node ) : ViewPosition.createBefore( node ), + startPosition: getNext ? ViewPosition._createAfter( node ) : ViewPosition._createBefore( node ), direction: getNext ? 'forward' : 'backward' } ); diff --git a/src/view/downcastwriter.js b/src/view/downcastwriter.js index 174732cbf..7f77e8a1e 100644 --- a/src/view/downcastwriter.js +++ b/src/view/downcastwriter.js @@ -8,11 +8,12 @@ */ import Position from './position'; +import Range from './range'; +import Selection from './selection'; import ContainerElement from './containerelement'; import AttributeElement from './attributeelement'; import EmptyElement from './emptyelement'; import UIElement from './uielement'; -import Range from './range'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import DocumentFragment from './documentfragment'; import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable'; @@ -21,11 +22,15 @@ import EditableElement from './editableelement'; import { isPlainObject } from 'lodash-es'; /** - * View downcast writer class. Provides set of methods used to properly manipulate nodes attached to - * {@link module:engine/view/document~Document view document}. It is not recommended to use it directly. To get an instance - * of view writer associated with the document use {@link module:engine/view/view~View#change view.change()) method. - * The `DowncastWriter` is designed to work with semantic view which is the view downcasted from model. For working with - * ordinary view (e.g. parsed from string) {@link module:engine/view/upcastwriter~UpcastWriter upcast writer} should be used. + * View downcast writer. + * + * It provides a set of methods used to manipulate view nodes. + * + * The `DowncastWriter` is designed to work with semantic views which are the views that were/are being downcasted from the model. + * To work with ordinary views (e.g. parsed from a string) use the {@link module:engine/view/upcastwriter~UpcastWriter upcast writer}. + * + * Do not create an instance of this writer manually. To modify a view structure, use + * the {@link module:engine/view/view~View#change View#change()) block. */ export default class DowncastWriter { constructor( document ) { @@ -52,26 +57,26 @@ export default class DowncastWriter { * {@link module:engine/view/item~Item item}, {@link module:engine/view/range~Range range}, * an iterable of {@link module:engine/view/range~Range ranges} or null. * - * ### Usage: + * Usage: * * // Sets selection to the given range. - * const range = new Range( start, end ); + * const range = writer.createRange( start, end ); * writer.setSelection( range ); * * // Sets backward selection to the given range. - * const range = new Range( start, end ); + * const range = writer.createRange( start, end ); * writer.setSelection( range ); * * // Sets selection to given ranges. - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; * writer.setSelection( range ); * * // Sets selection to the other selection. - * const otherSelection = new Selection(); + * const otherSelection = writer.createSelection(); * writer.setSelection( otherSelection ); * * // Sets collapsed selection at the given position. - * const position = new Position( root, path ); + * const position = writer.createPositionFromPath( root, path ); * writer.setSelection( position ); * * // Sets collapsed selection at the position of given item and offset. @@ -120,7 +125,8 @@ export default class DowncastWriter { /** * Moves {@link module:engine/view/documentselection~DocumentSelection#focus selection's focus} to the specified location. * - * The location can be specified in the same form as {@link module:engine/view/position~Position.createAt} parameters. + * The location can be specified in the same form as {@link module:engine/view/view~View#createPositionAt view.createPositionAt()} + * parameters. * * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when @@ -452,19 +458,19 @@ export default class DowncastWriter { } if ( position.isAtStart ) { - return Position.createBefore( element ); + return Position._createBefore( element ); } else if ( !position.isAtEnd ) { const newElement = element._clone( false ); - this.insert( Position.createAfter( element ), newElement ); + this.insert( Position._createAfter( element ), newElement ); - const sourceRange = new Range( position, Position.createAt( element, 'end' ) ); + const sourceRange = new Range( position, Position._createAt( element, 'end' ) ); const targetPosition = new Position( newElement, 0 ); this.move( sourceRange, targetPosition ); } - return Position.createAfter( element ); + return Position._createAfter( element ); } /** @@ -575,10 +581,10 @@ export default class DowncastWriter { } const lastChild = prev.getChild( prev.childCount - 1 ); - const newPosition = lastChild instanceof Text ? Position.createAt( lastChild, 'end' ) : Position.createAt( prev, 'end' ); + const newPosition = lastChild instanceof Text ? Position._createAt( lastChild, 'end' ) : Position._createAt( prev, 'end' ); - this.move( Range.createIn( next ), Position.createAt( prev, 'end' ) ); - this.remove( Range.createOn( next ) ); + this.move( Range._createIn( next ), Position._createAt( prev, 'end' ) ); + this.remove( Range._createOn( next ) ); return newPosition; } @@ -657,7 +663,7 @@ export default class DowncastWriter { * @returns {module:engine/view/documentfragment~DocumentFragment} Document fragment containing removed nodes. */ remove( rangeOrItem ) { - const range = rangeOrItem instanceof Range ? rangeOrItem : Range.createOn( rangeOrItem ); + const range = rangeOrItem instanceof Range ? rangeOrItem : Range._createOn( rangeOrItem ); validateRangeContainer( range ); @@ -682,7 +688,7 @@ export default class DowncastWriter { // Merge after removing. const mergePosition = this.mergeAttributes( breakStart ); range.start = mergePosition; - range.end = Position.createFromPosition( mergePosition ); + range.end = mergePosition.clone(); // Return removed nodes. return new DocumentFragment( removed ); @@ -716,7 +722,7 @@ export default class DowncastWriter { // When current item matches to the given element. if ( item.is( 'element' ) && element.isSimilar( item ) ) { // Create range on this element. - rangeToRemove = Range.createOn( item ); + rangeToRemove = Range._createOn( item ); // When range starts inside Text or TextProxy element. } else if ( !current.nextPosition.isAfter( range.start ) && item.is( 'textProxy' ) ) { // We need to check if parent of this text matches to given element. @@ -726,7 +732,7 @@ export default class DowncastWriter { // If it is then create range inside this element. if ( parentElement ) { - rangeToRemove = Range.createIn( parentElement ); + rangeToRemove = Range._createIn( parentElement ); } } @@ -914,9 +920,9 @@ export default class DowncastWriter { rename( newName, viewElement ) { const newElement = new ContainerElement( newName, viewElement.getAttributes() ); - this.insert( Position.createAfter( viewElement ), newElement ); - this.move( Range.createIn( viewElement ), Position.createAt( newElement, 0 ) ); - this.remove( Range.createOn( viewElement ) ); + this.insert( Position._createAfter( viewElement ), newElement ); + this.move( Range._createIn( viewElement ), Position._createAt( newElement, 0 ) ); + this.remove( Range._createOn( viewElement ) ); return newElement; } @@ -939,6 +945,147 @@ export default class DowncastWriter { this._cloneGroups.delete( groupName ); } + /** + * Creates position at the given location. The location can be specified as: + * + * * a {@link module:engine/view/position~Position position}, + * * parent element and offset (offset defaults to `0`), + * * parent element and `'end'` (sets position at the end of that element), + * * {@link module:engine/view/item~Item view item} and `'before'` or `'after'` (sets position before or after given view item). + * + * This method is a shortcut to other constructors such as: + * + * * {@link #createPositionBefore}, + * * {@link #createPositionAfter}, + * + * @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition + * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when + * first parameter is a {@link module:engine/view/item~Item view item}. + */ + createPositionAt( itemOrPosition, offset ) { + return Position._createAt( itemOrPosition, offset ); + } + + /** + * Creates a new position after given view item. + * + * @param {module:engine/view/item~Item} item View item after which the position should be located. + * @returns {module:engine/view/position~Position} + */ + createPositionAfter( item ) { + return Position._createAfter( item ); + } + + /** + * Creates a new position before given view item. + * + * @param {module:engine/view/item~Item} item View item before which the position should be located. + * @returns {module:engine/view/position~Position} + */ + createPositionBefore( item ) { + return Position._createBefore( item ); + } + + /** + * Creates a range spanning from `start` position to `end` position. + * + * **Note:** This factory method creates it's own {@link module:engine/view/position~Position} instances basing on passed values. + * + * @param {module:engine/view/position~Position} start Start position. + * @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at `start` position. + * @returns {module:engine/view/range~Range} + */ + createRange( start, end ) { + return new Range( start, end ); + } + + /** + * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it. + * + * @param {module:engine/view/item~Item} item + * @returns {module:engine/view/range~Range} + */ + createRangeOn( item ) { + return Range._createOn( item ); + } + + /** + * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of + * that element and ends after the last child of that element. + * + * @param {module:engine/view/element~Element} element Element which is a parent for the range. + * @returns {module:engine/view/range~Range} + */ + createRangeIn( element ) { + return Range._createIn( element ); + } + + /** + Creates new {@link module:engine/view/selection~Selection} instance. + * + * // Creates empty selection without ranges. + * const selection = writer.createSelection(); + * + * // Creates selection at the given range. + * const range = writer.createRange( start, end ); + * const selection = writer.createSelection( range ); + * + * // Creates selection at the given ranges + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; + * const selection = writer.createSelection( ranges ); + * + * // Creates selection from the other selection. + * const otherSelection = writer.createSelection(); + * const selection = writer.createSelection( otherSelection ); + * + * // Creates selection from the document selection. + * const selection = writer.createSelection( editor.editing.view.document.selection ); + * + * // Creates selection at the given position. + * const position = writer.createPositionFromPath( root, path ); + * const selection = writer.createSelection( position ); + * + * // Creates collapsed selection at the position of given item and offset. + * const paragraph = writer.createContainerElement( 'paragraph' ); + * const selection = writer.createSelection( paragraph, offset ); + * + * // Creates a range inside an {@link module:engine/view/element~Element element} which starts before the + * // first child of that element and ends after the last child of that element. + * const selection = writer.createSelection( paragraph, 'in' ); + * + * // Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends + * // just after the item. + * const selection = writer.createSelection( paragraph, 'on' ); + * + * `Selection`'s constructor allow passing additional options (`backward`, `fake` and `label`) as the last argument. + * + * // Creates backward selection. + * const selection = writer.createSelection( range, { backward: true } ); + * + * Fake selection does not render as browser native selection over selected elements and is hidden to the user. + * This way, no native selection UI artifacts are displayed to the user and selection over elements can be + * represented in other way, for example by applying proper CSS class. + * + * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM + * (and be properly handled by screen readers). + * + * // Creates fake selection with label. + * const selection = writer.createSelection( range, { fake: true, label: 'foo' } ); + * + * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection| + * module:engine/view/position~Position|Iterable.|module:engine/view/range~Range| + * module:engine/view/item~Item|null} [selectable=null] + * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`. + * @param {Object} [options] + * @param {Boolean} [options.backward] Sets this selection instance to be backward. + * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`. + * @param {String} [options.label] Label for the fake selection. + * @returns {module:engine/view/selection~Selection} + */ + createSelection( selectable, placeOrOffset, options ) { + return new Selection( selectable, placeOrOffset, options ); + } + /** * Wraps children with provided `attribute`. Only children contained in `parent` element between * `startOffset` and `endOffset` will be wrapped. @@ -1002,7 +1149,7 @@ export default class DowncastWriter { } } - return Range.createFromParentsAndOffsets( parent, startOffset, parent, endOffset ); + return Range._createFromParentsAndOffsets( parent, startOffset, parent, endOffset ); } /** @@ -1074,7 +1221,7 @@ export default class DowncastWriter { } } - return Range.createFromParentsAndOffsets( parent, startOffset, parent, endOffset ); + return Range._createFromParentsAndOffsets( parent, startOffset, parent, endOffset ); } /** @@ -1094,8 +1241,8 @@ export default class DowncastWriter { if ( rangeSpansOnAllChildren( range ) && this._wrapAttributeElement( attribute, range.start.parent ) ) { const parent = range.start.parent; - const end = this.mergeAttributes( Position.createAfter( parent ) ); - const start = this.mergeAttributes( Position.createBefore( parent ) ); + const end = this.mergeAttributes( Position._createAfter( parent ) ); + const start = this.mergeAttributes( Position._createBefore( parent ) ); return new Range( start, end ); } @@ -1155,7 +1302,7 @@ export default class DowncastWriter { _wrapPosition( position, attribute ) { // Return same position when trying to wrap with attribute similar to position parent. if ( attribute.isSimilar( position.parent ) ) { - return movePositionToTextNode( Position.createFromPosition( position ) ); + return movePositionToTextNode( position.clone() ); } // When position is inside text node - break it and place new position between two text nodes. @@ -1399,12 +1546,12 @@ export default class DowncastWriter { // There are no attributes to break and text nodes breaking is not forced. if ( !forceSplitText && positionParent.is( 'text' ) && isContainerOrFragment( positionParent.parent ) ) { - return Position.createFromPosition( position ); + return position.clone(); } // Position's parent is container, so no attributes to break. if ( isContainerOrFragment( positionParent ) ) { - return Position.createFromPosition( position ); + return position.clone(); } // Break text and start again in new position. diff --git a/src/view/editableelement.js b/src/view/editableelement.js index 5b16f6c42..32bedb24d 100644 --- a/src/view/editableelement.js +++ b/src/view/editableelement.js @@ -63,6 +63,17 @@ export default class EditableElement extends ContainerElement { */ } + /** + * @inheritDoc + */ + is( type, name = null ) { + if ( !name ) { + return type == 'editableElement' || super.is( type ); + } else { + return ( type == 'editableElement' && name == this.name ) || super.is( type, name ); + } + } + /** * Returns document associated with the editable. * diff --git a/src/view/position.js b/src/view/position.js index c62eeb225..fc77cb55b 100644 --- a/src/view/position.js +++ b/src/view/position.js @@ -131,7 +131,7 @@ export default class Position { * @returns {module:engine/view/position~Position} Shifted position. */ getShiftedBy( shift ) { - const shifted = Position.createFromPosition( this ); + const shifted = Position._createAt( this ); const offset = shifted.offset + shift; shifted.offset = offset < 0 ? 0 : offset; @@ -274,6 +274,25 @@ export default class Position { } } + /** + * Creates a {@link module:engine/view/treewalker~TreeWalker TreeWalker} instance with this positions as a start position. + * + * @param {Object} options Object with configuration options. See {@link module:engine/view/treewalker~TreeWalker} + * @param {module:engine/view/range~Range} [options.boundaries=null] Range to define boundaries of the iterator. + * @param {Boolean} [options.singleCharacters=false] + * @param {Boolean} [options.shallow=false] + * @param {Boolean} [options.ignoreElementEnd=false] + */ + getWalker( options = {} ) { + options.startPosition = this; + + return new TreeWalker( options ); + } + + clone() { + return new Position( this.parent, this.offset ); + } + /** * Creates position at the given location. The location can be specified as: * @@ -284,36 +303,36 @@ export default class Position { * * This method is a shortcut to other constructors such as: * - * * {@link module:engine/view/position~Position.createBefore}, - * * {@link module:engine/view/position~Position.createAfter}, - * * {@link module:engine/view/position~Position.createFromPosition}. + * * {@link module:engine/view/position~Position._createBefore}, + * * {@link module:engine/view/position~Position._createAfter}. * + * @protected * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when * first parameter is a {@link module:engine/view/item~Item view item}. */ - static createAt( itemOrPosition, offset ) { + static _createAt( itemOrPosition, offset ) { if ( itemOrPosition instanceof Position ) { - return this.createFromPosition( itemOrPosition ); + return new this( itemOrPosition.parent, itemOrPosition.offset ); } else { const node = itemOrPosition; if ( offset == 'end' ) { offset = node.is( 'text' ) ? node.data.length : node.childCount; } else if ( offset == 'before' ) { - return this.createBefore( node ); + return this._createBefore( node ); } else if ( offset == 'after' ) { - return this.createAfter( node ); + return this._createAfter( node ); } else if ( offset !== 0 && !offset ) { /** - * {@link module:engine/view/position~Position.createAt `Position.createAt()`} + * {@link module:engine/view/view~View#createPositionAt `View#createPositionAt()`} * requires the offset to be specified when the first parameter is a view item. * - * @error view-position-createAt-offset-required + * @error view-createPositionAt-offset-required */ throw new CKEditorError( - 'view-position-createAt-offset-required: ' + - 'Position.createAt() requires the offset when the first parameter is a view item.' ); + 'view-createPositionAt-offset-required: ' + + 'View#createPositionAt() requires the offset when the first parameter is a view item.' ); } return new Position( node, offset ); @@ -323,10 +342,11 @@ export default class Position { /** * Creates a new position after given view item. * + * @protected * @param {module:engine/view/item~Item} item View item after which the position should be located. * @returns {module:engine/view/position~Position} */ - static createAfter( item ) { + static _createAfter( item ) { // TextProxy is not a instance of Node so we need do handle it in specific way. if ( item.is( 'textProxy' ) ) { return new Position( item.textNode, item.offsetInText + item.data.length ); @@ -348,10 +368,11 @@ export default class Position { /** * Creates a new position before given view item. * + * @protected * @param {module:engine/view/item~Item} item View item before which the position should be located. * @returns {module:engine/view/position~Position} */ - static createBefore( item ) { + static _createBefore( item ) { // TextProxy is not a instance of Node so we need do handle it in specific way. if ( item.is( 'textProxy' ) ) { return new Position( item.textNode, item.offsetInText ); @@ -369,16 +390,6 @@ export default class Position { return new Position( item.parent, item.index ); } - - /** - * Creates and returns a new instance of `Position`, which is equal to the passed position. - * - * @param {module:engine/view/position~Position} position Position to be cloned. - * @returns {module:engine/view/position~Position} - */ - static createFromPosition( position ) { - return new this( position.parent, position.offset ); - } } /** diff --git a/src/view/range.js b/src/view/range.js index 75572ca94..2aeb2b775 100644 --- a/src/view/range.js +++ b/src/view/range.js @@ -29,7 +29,7 @@ export default class Range { * @readonly * @member {module:engine/view/position~Position} */ - this.start = Position.createFromPosition( start ); + this.start = start.clone(); /** * End position. @@ -37,7 +37,7 @@ export default class Range { * @readonly * @member {module:engine/view/position~Position} */ - this.end = end ? Position.createFromPosition( end ) : Position.createFromPosition( start ); + this.end = end ? end.clone() : start.clone(); } /** @@ -107,11 +107,11 @@ export default class Range { // Fix positions, in case if they are in Text node. if ( start.parent.is( 'text' ) && start.isAtStart ) { - start = Position.createBefore( start.parent ); + start = Position._createBefore( start.parent ); } if ( end.parent.is( 'text' ) && end.isAtEnd ) { - end = Position.createAfter( end.parent ); + end = Position._createAfter( end.parent ); } return new Range( start, end ); @@ -210,16 +210,19 @@ export default class Range { * let bar = new Text( 'bar' ); * let p = new ContainerElement( 'p', null, [ foo, img, bar ] ); * - * let range = new Range( new Position( foo, 2 ), new Position( bar, 1 ); // "o", img, "b" are in range. - * let otherRange = new Range( new Position( foo, 1 ), new Position( bar, 2 ); "oo", img, "ba" are in range. + * let range = view.createRange( view.createPositionAt( foo, 2 ), view.createPositionAt( bar, 1 ); // "o", img, "b" are in range. + * let otherRange = view.createRange( // "oo", img, "ba" are in range. + * view.createPositionAt( foo, 1 ), + * view.createPositionAt( bar, 2 ) + * ); * let transformed = range.getDifference( otherRange ); * // transformed array has no ranges because `otherRange` contains `range` * - * otherRange = new Range( new Position( foo, 1 ), new Position( p, 2 ); // "oo", img are in range. + * otherRange = view.createRange( view.createPositionAt( foo, 1 ), view.createPositionAt( p, 2 ); // "oo", img are in range. * transformed = range.getDifference( otherRange ); * // transformed array has one range: from ( p, 2 ) to ( bar, 1 ) * - * otherRange = new Range( new Position( p, 1 ), new Position( p, 2 ) ); // img is in range. + * otherRange = view.createRange( view.createPositionAt( p, 1 ), view.createPositionAt( p, 2 ) ); // img is in range. * transformed = range.getDifference( otherRange ); * // transformed array has two ranges: from ( foo, 1 ) to ( p, 1 ) and from ( p, 2 ) to ( bar, 1 ) * @@ -245,7 +248,7 @@ export default class Range { } } else { // Ranges do not intersect, return the original range. - ranges.push( Range.createFromRange( this ) ); + ranges.push( this.clone() ); } return ranges; @@ -262,11 +265,11 @@ export default class Range { * let bar = new Text( 'bar' ); * let p = new ContainerElement( 'p', null, [ foo, img, bar ] ); * - * let range = new Range( new Position( foo, 2 ), new Position( bar, 1 ); // "o", img, "b" are in range. - * let otherRange = new Range( new Position( foo, 1 ), new Position( p, 2 ); // "oo", img are in range. + * let range = view.createRange( view.createPositionAt( foo, 2 ), view.createPositionAt( bar, 1 ); // "o", img, "b" are in range. + * let otherRange = view.createRange( view.createPositionAt( foo, 1 ), view.createPositionAt( p, 2 ); // "oo", img are in range. * let transformed = range.getIntersection( otherRange ); // range from ( foo, 1 ) to ( p, 2 ). * - * otherRange = new Range( new Position( bar, 1 ), new Position( bar, 3 ); "ar" is in range. + * otherRange = view.createRange( view.createPositionAt( bar, 1 ), view.createPositionAt( bar, 3 ); "ar" is in range. * transformed = range.getIntersection( otherRange ); // null - no common part. * * @param {module:engine/view/range~Range} otherRange Range to check for intersection. @@ -323,6 +326,10 @@ export default class Range { return this.start.getCommonAncestor( this.end ); } + clone() { + return new Range( this.start, this.end ); + } + /** * Returns an iterator that iterates over all {@link module:engine/view/item~Item view items} that are in this range and returns * them. @@ -386,6 +393,7 @@ export default class Range { /** * Creates a range from given parents and offsets. * + * @protected * @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} startElement Start position * parent element. * @param {Number} startOffset Start position offset. @@ -394,32 +402,23 @@ export default class Range { * @param {Number} endOffset End position offset. * @returns {module:engine/view/range~Range} Created range. */ - static createFromParentsAndOffsets( startElement, startOffset, endElement, endOffset ) { + static _createFromParentsAndOffsets( startElement, startOffset, endElement, endOffset ) { return new this( new Position( startElement, startOffset ), new Position( endElement, endOffset ) ); } - /** - * Creates and returns a new instance of Range which is equal to passed range. - * - * @param {module:engine/view/range~Range} range Range to clone. - * @returns {module:engine/view/range~Range} - */ - static createFromRange( range ) { - return new this( range.start, range.end ); - } - /** * Creates a new range, spreading from specified {@link module:engine/view/position~Position position} to a position moved by * given `shift`. If `shift` is a negative value, shifted position is treated as the beginning of the range. * + * @protected * @param {module:engine/view/position~Position} position Beginning of the range. * @param {Number} shift How long the range should be. * @returns {module:engine/view/range~Range} */ - static createFromPositionAndShift( position, shift ) { + static _createFromPositionAndShift( position, shift ) { const start = position; const end = position.getShiftedBy( shift ); @@ -430,38 +429,25 @@ export default class Range { * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of * that element and ends after the last child of that element. * + * @protected * @param {module:engine/view/element~Element} element Element which is a parent for the range. * @returns {module:engine/view/range~Range} */ - static createIn( element ) { - return this.createFromParentsAndOffsets( element, 0, element, element.childCount ); + static _createIn( element ) { + return this._createFromParentsAndOffsets( element, 0, element, element.childCount ); } /** * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it. * + * @protected * @param {module:engine/view/item~Item} item * @returns {module:engine/view/range~Range} */ - static createOn( item ) { + static _createOn( item ) { const size = item.is( 'textProxy' ) ? item.offsetSize : 1; - return this.createFromPositionAndShift( Position.createBefore( item ), size ); - } - - /** - * Creates a collapsed range at given {@link module:engine/view/position~Position position} - * or on the given {@link module:engine/view/item~Item item}. - * - * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition - * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when - * first parameter is a {@link module:engine/view/item~Item view item}. - */ - static createCollapsedAt( itemOrPosition, offset ) { - const start = Position.createAt( itemOrPosition, offset ); - const end = Position.createFromPosition( start ); - - return new Range( start, end ); + return this._createFromPositionAndShift( Position._createBefore( item ), size ); } } diff --git a/src/view/renderer.js b/src/view/renderer.js index 934ed80a0..2c7a0aa41 100644 --- a/src/view/renderer.js +++ b/src/view/renderer.js @@ -333,7 +333,7 @@ export default class Renderer { const firstPos = this.selection.getFirstPosition(); if ( firstPos.parent.is( 'text' ) ) { - return ViewPosition.createBefore( this.selection.getFirstPosition().parent ); + return ViewPosition._createBefore( this.selection.getFirstPosition().parent ); } else { return firstPos; } diff --git a/src/view/selection.js b/src/view/selection.js index f6d1190ee..c67f25191 100644 --- a/src/view/selection.js +++ b/src/view/selection.js @@ -19,63 +19,64 @@ import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable'; import DocumentSelection from './documentselection'; /** - * Class representing selection in tree view. + * Class representing an arbirtary selection in the view. + * See also {@link module:engine/view/documentselection~DocumentSelection}. * - * Selection can consist of {@link module:engine/view/range~Range ranges} that can be set using - * {@link module:engine/view/selection~Selection#setTo setTo} method. - * That method create copies of provided ranges and store those copies internally. Further modifications to passed - * ranges will not change selection's state. - * Selection's ranges can be obtained via {@link module:engine/view/selection~Selection#getRanges getRanges}, - * {@link module:engine/view/selection~Selection#getFirstRange getFirstRange} and - * {@link module:engine/view/selection~Selection#getLastRange getLastRange} methods, which return copies of ranges - * stored inside selection. Modifications made on these copies will not change selection's state. Similar situation - * occurs when getting {@link module:engine/view/selection~Selection#anchor anchor}, - * {@link module:engine/view/selection~Selection#focus focus}, {@link module:engine/view/selection~Selection#getFirstPosition first} - * and {@link module:engine/view/selection~Selection#getLastPosition last} positions - all will return - * copies of requested positions. + * New selection instances can be created via the constructor or one these methods: + * + * * {@link module:engine/view/view~View#createSelection `View#createSelection()`}, + * * {@link module:engine/view/upcastwriter~UpcastWriter#createSelection `UpcastWriter#createSelection()`}. + * + * A selection can consist of {@link module:engine/view/range~Range ranges} that can be set by using + * the {@link module:engine/view/selection~Selection#setTo `Selection#setTo()`} method. */ export default class Selection { /** * Creates new selection instance. * + * **Note**: The selection constructor is available as a factory method: + * + * * {@link module:engine/view/view~View#createSelection `View#createSelection()`}, + * * {@link module:engine/view/upcastwriter~UpcastWriter#createSelection `UpcastWriter#createSelection()`}. + * * // Creates empty selection without ranges. - * const selection = new Selection(); + * const selection = writer.createSelection(); * * // Creates selection at the given range. - * const range = new Range( start, end ); - * const selection = new Selection( range ); + * const range = writer.createRange( start, end ); + * const selection = writer.createSelection( range ); * * // Creates selection at the given ranges - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; - * const selection = new Selection( ranges ); + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; + * const selection = writer.createSelection( ranges ); * * // Creates selection from the other selection. - * const otherSelection = new Selection(); - * const selection = new Selection( otherSelection ); + * const otherSelection = writer.createSelection(); + * const selection = writer.createSelection( otherSelection ); * * // Creates selection from the document selection. - * const selection = new Selection( editor.editing.view.document.selection ); + * const selection = writer.createSelection( editor.editing.view.document.selection ); * * // Creates selection at the given position. - * const position = new Position( root, path ); - * const selection = new Selection( position ); + * const position = writer.createPositionFromPath( root, path ); + * const selection = writer.createSelection( position ); * * // Creates collapsed selection at the position of given item and offset. * const paragraph = writer.createContainerElement( 'paragraph' ); - * const selection = new Selection( paragraph, offset ); + * const selection = writer.createSelection( paragraph, offset ); * * // Creates a range inside an {@link module:engine/view/element~Element element} which starts before the * // first child of that element and ends after the last child of that element. - * const selection = new Selection( paragraph, 'in' ); + * const selection = writer.createSelection( paragraph, 'in' ); * * // Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends * // just after the item. - * const selection = new Selection( paragraph, 'on' ); + * const selection = writer.createSelection( paragraph, 'on' ); * * `Selection`'s constructor allow passing additional options (`backward`, `fake` and `label`) as the last argument. * * // Creates backward selection. - * const selection = new Selection( range, { backward: true } ); + * const selection = writer.createSelection( range, { backward: true } ); * * Fake selection does not render as browser native selection over selected elements and is hidden to the user. * This way, no native selection UI artifacts are displayed to the user and selection over elements can be @@ -85,7 +86,7 @@ export default class Selection { * (and be properly handled by screen readers). * * // Creates fake selection with label. - * const selection = new Selection( range, { fake: true, label: 'foo' } ); + * const selection = writer.createSelection( range, { fake: true, label: 'foo' } ); * * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection| * module:engine/view/position~Position|Iterable.|module:engine/view/range~Range| @@ -168,7 +169,7 @@ export default class Selection { const range = this._ranges[ this._ranges.length - 1 ]; const anchor = this._lastRangeBackward ? range.end : range.start; - return Position.createFromPosition( anchor ); + return anchor.clone(); } /** @@ -184,7 +185,7 @@ export default class Selection { const range = this._ranges[ this._ranges.length - 1 ]; const focus = this._lastRangeBackward ? range.start : range.end; - return Position.createFromPosition( focus ); + return focus.clone(); } /** @@ -236,7 +237,7 @@ export default class Selection { */ * getRanges() { for ( const range of this._ranges ) { - yield Range.createFromRange( range ); + yield range.clone(); } } @@ -257,7 +258,7 @@ export default class Selection { } } - return first ? Range.createFromRange( first ) : null; + return first ? first.clone() : null; } /** @@ -276,7 +277,7 @@ export default class Selection { } } - return last ? Range.createFromRange( last ) : null; + return last ? last.clone() : null; } /** @@ -289,7 +290,7 @@ export default class Selection { getFirstPosition() { const firstRange = this.getFirstRange(); - return firstRange ? Position.createFromPosition( firstRange.start ) : null; + return firstRange ? firstRange.start.clone() : null; } /** @@ -302,7 +303,7 @@ export default class Selection { getLastPosition() { const lastRange = this.getLastRange(); - return lastRange ? Position.createFromPosition( lastRange.end ) : null; + return lastRange ? lastRange.end.clone() : null; } /** @@ -429,22 +430,22 @@ export default class Selection { * an iterable of {@link module:engine/view/range~Range ranges} or null. * * // Sets selection to the given range. - * const range = new Range( start, end ); + * const range = writer.createRange( start, end ); * selection.setTo( range ); * * // Sets selection to given ranges. - * const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ]; + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; * selection.setTo( range ); * * // Sets selection to the other selection. - * const otherSelection = new Selection(); + * const otherSelection = writer.createSelection(); * selection.setTo( otherSelection ); * * // Sets selection to contents of DocumentSelection. * selection.setTo( editor.editing.view.document.selection ); * * // Sets collapsed selection at the given position. - * const position = new Position( root, path ); + * const position = writer.createPositionAt( root, path ); * selection.setTo( position ); * * // Sets collapsed selection at the position of given item and offset. @@ -515,11 +516,11 @@ export default class Selection { 'selection.setTo requires the second parameter when the first parameter is a node.' ); } else if ( placeOrOffset == 'in' ) { - range = Range.createIn( selectable ); + range = Range._createIn( selectable ); } else if ( placeOrOffset == 'on' ) { - range = Range.createOn( selectable ); + range = Range._createOn( selectable ); } else { - range = Range.createCollapsedAt( selectable, placeOrOffset ); + range = new Range( Position._createAt( selectable, placeOrOffset ) ); } this._setRanges( [ range ], backward ); @@ -544,7 +545,8 @@ export default class Selection { /** * Moves {@link #focus} to the specified location. * - * The location can be specified in the same form as {@link module:engine/view/position~Position.createAt} parameters. + * The location can be specified in the same form as {@link module:engine/view/view~View#createPositionAt view.createPositionAt()} + * parameters. * * @fires change * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition @@ -563,7 +565,7 @@ export default class Selection { ); } - const newFocus = Position.createAt( itemOrPosition, offset ); + const newFocus = Position._createAt( itemOrPosition, offset ); if ( newFocus.compareWith( this.focus ) == 'same' ) { return; @@ -684,7 +686,7 @@ export default class Selection { } } - this._ranges.push( Range.createFromRange( range ) ); + this._ranges.push( new Range( range.start, range.end ) ); } /** diff --git a/src/view/treewalker.js b/src/view/treewalker.js index 5da59a228..83520b188 100644 --- a/src/view/treewalker.js +++ b/src/view/treewalker.js @@ -73,9 +73,9 @@ export default class TreeWalker { * @member {module:engine/view/position~Position} module:engine/view/treewalker~TreeWalker#position */ if ( options.startPosition ) { - this.position = Position.createFromPosition( options.startPosition ); + this.position = Position._createAt( options.startPosition ); } else { - this.position = Position.createFromPosition( options.boundaries[ options.direction == 'backward' ? 'end' : 'start' ] ); + this.position = Position._createAt( options.boundaries[ options.direction == 'backward' ? 'end' : 'start' ] ); } /** @@ -189,7 +189,7 @@ export default class TreeWalker { * @returns {module:engine/view/treewalker~TreeWalkerValue} return.value Information about taken step. */ _next() { - let position = Position.createFromPosition( this.position ); + let position = this.position.clone(); const previousPosition = this.position; const parent = position.parent; @@ -210,7 +210,7 @@ export default class TreeWalker { if ( parent instanceof Text ) { if ( position.isAtEnd ) { // Prevent returning "elementEnd" for Text node. Skip that value and return the next walker step. - this.position = Position.createAfter( parent ); + this.position = Position._createAfter( parent ); return this._next(); } @@ -244,7 +244,7 @@ export default class TreeWalker { if ( node == this._boundaryEndParent ) { charactersCount = this.boundaries.end.offset; item = new TextProxy( node, 0, charactersCount ); - position = Position.createAfter( item ); + position = Position._createAfter( item ); } else { item = new TextProxy( node, 0, node.data.length ); // If not just keep moving forward. @@ -275,7 +275,7 @@ export default class TreeWalker { return this._formatReturnValue( 'text', textProxy, previousPosition, position, textLength ); } else { // `node` is not set, we reached the end of current `parent`. - position = Position.createAfter( parent ); + position = Position._createAfter( parent ); this.position = position; if ( this.ignoreElementEnd ) { @@ -295,7 +295,7 @@ export default class TreeWalker { * @returns {module:engine/view/treewalker~TreeWalkerValue} return.value Information about taken step. */ _previous() { - let position = Position.createFromPosition( this.position ); + let position = this.position.clone(); const previousPosition = this.position; const parent = position.parent; @@ -316,7 +316,7 @@ export default class TreeWalker { if ( parent instanceof Text ) { if ( position.isAtStart ) { // Prevent returning "elementStart" for Text node. Skip that value and return the next walker step. - this.position = Position.createBefore( parent ); + this.position = Position._createBefore( parent ); return this._previous(); } @@ -358,7 +358,7 @@ export default class TreeWalker { item = new TextProxy( node, offset, node.data.length - offset ); charactersCount = item.data.length; - position = Position.createBefore( item ); + position = Position._createBefore( item ); } else { item = new TextProxy( node, 0, node.data.length ); // If not just keep moving backward. @@ -390,7 +390,7 @@ export default class TreeWalker { return this._formatReturnValue( 'text', textProxy, previousPosition, position, textLength ); } else { // `node` is not set, we reached the beginning of current `parent`. - position = Position.createBefore( parent ); + position = Position._createBefore( parent ); this.position = position; return this._formatReturnValue( 'elementStart', parent, previousPosition, position, 1 ); @@ -417,22 +417,22 @@ export default class TreeWalker { // Position is at the end of Text. if ( item.offsetInText + item.data.length == item.textNode.data.length ) { if ( this.direction == 'forward' && !( this.boundaries && this.boundaries.end.isEqual( this.position ) ) ) { - nextPosition = Position.createAfter( item.textNode ); + nextPosition = Position._createAfter( item.textNode ); // When we change nextPosition of returned value we need also update walker current position. this.position = nextPosition; } else { - previousPosition = Position.createAfter( item.textNode ); + previousPosition = Position._createAfter( item.textNode ); } } // Position is at the begining ot the text. if ( item.offsetInText === 0 ) { if ( this.direction == 'backward' && !( this.boundaries && this.boundaries.start.isEqual( this.position ) ) ) { - nextPosition = Position.createBefore( item.textNode ); + nextPosition = Position._createBefore( item.textNode ); // When we change nextPosition of returned value we need also update walker current position. this.position = nextPosition; } else { - previousPosition = Position.createBefore( item.textNode ); + previousPosition = Position._createBefore( item.textNode ); } } } @@ -464,24 +464,24 @@ export default class TreeWalker { * * @typedef {Object} module:engine/view/treewalker~TreeWalkerValue * @property {module:engine/view/treewalker~TreeWalkerValueType} type - * @property {module:engine/view/item~Item} item Item between old and new positions of {@link module:engine/view/treewalker~TreeWalker}. + * @property {module:engine/view/item~Item} item Item between the old and the new positions + * of the tree walker. * @property {module:engine/view/position~Position} previousPosition Previous position of the iterator. * * Forward iteration: For `'elementEnd'` it is the last position inside the element. For all other types it is the - * position before the item. Note that it is more efficient to use this position then calculate the position before - * the node using {@link module:engine/view/position~Position.createBefore}. + * position before the item. * * Backward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is * the position after item. * * If the position is at the beginning or at the end of the {@link module:engine/view/text~Text} it is always moved from the - * inside of the Text to its parent just before or just after Text. + * inside of the text to its parent just before or just after that text. * @property {module:engine/view/position~Position} nextPosition Next position of the iterator. * * Forward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is * the position after the item. * * Backward iteration: For `'elementEnd'` it is last position inside element. For all other types it is the position * before the item. * * If the position is at the beginning or at the end of the {@link module:engine/view/text~Text} it is always moved from the - * inside of the Text to its parent just before or just after Text. - * @property {Number} [length] Length of the item. For `'elementStart'` it is 1. For `'text'` it is - * the length of the text. For `'elementEnd'` it is undefined. + * inside of the text to its parent just before or just after that text. + * @property {Number} [length] Length of the item. For `'elementStart'` it is `1`. For `'text'` it is + * the length of that text. For `'elementEnd'` it is `undefined`. */ /** diff --git a/src/view/upcastwriter.js b/src/view/upcastwriter.js index 2599a9490..2c106d4c4 100644 --- a/src/view/upcastwriter.js +++ b/src/view/upcastwriter.js @@ -9,16 +9,22 @@ import Element from './element'; import { isPlainObject } from 'lodash-es'; +import Position from './position'; +import Range from './range'; +import Selection from './selection'; /** - * View upcast writer class. Provides set of methods used to properly manipulate nodes attached to - * {@link module:engine/view/view~View view instance}. It should be only used to manipulate non-semantic view - * (view created from HTML string). For view which was downcasted from the {@link module:engine/model/model~Model model} - * see {@link module:engine/view/downcastwriter~DowncastWriter writer}. + * View upcast writer. + * + * It provides a set of methods used to manipulate view nodes. + * It should be used only while working on a non-semantic view + * (e.g. a view created from HTML string on paste). + * To manipulate a view which was or is being downcasted from the the model use the + * {@link module:engine/view/downcastwriter~DowncastWriter downcast writer}. */ export default class UpcastWriter { /** - * Clones provided element. + * Clones the provided element. * * @see module:engine/view/element~Element#_clone * @param {module:engine/view/element~Element} element Element to be cloned. @@ -62,7 +68,7 @@ export default class UpcastWriter { } /** - * Removes number of child nodes starting at the given index and set the parent of these nodes to `null`. + * Removes the given number of child nodes starting at the given index and set the parent of these nodes to `null`. * * @see module:engine/view/element~Element#_removeChildren * @param {Number} index Offset from which nodes will be removed. @@ -245,4 +251,145 @@ export default class UpcastWriter { removeCustomProperty( key, element ) { return element._removeCustomProperty( key ); } + + /** + * Creates position at the given location. The location can be specified as: + * + * * a {@link module:engine/view/position~Position position}, + * * parent element and offset (offset defaults to `0`), + * * parent element and `'end'` (sets position at the end of that element), + * * {@link module:engine/view/item~Item view item} and `'before'` or `'after'` (sets position before or after given view item). + * + * This method is a shortcut to other constructors such as: + * + * * {@link #createPositionBefore}, + * * {@link #createPositionAfter}, + * + * @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition + * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when + * first parameter is a {@link module:engine/view/item~Item view item}. + */ + createPositionAt( itemOrPosition, offset ) { + return Position._createAt( itemOrPosition, offset ); + } + + /** + * Creates a new position after given view item. + * + * @param {module:engine/view/item~Item} item View item after which the position should be located. + * @returns {module:engine/view/position~Position} + */ + createPositionAfter( item ) { + return Position._createAfter( item ); + } + + /** + * Creates a new position before given view item. + * + * @param {module:engine/view/item~Item} item View item before which the position should be located. + * @returns {module:engine/view/position~Position} + */ + createPositionBefore( item ) { + return Position._createBefore( item ); + } + + /** + * Creates a range spanning from `start` position to `end` position. + * + * **Note:** This factory method creates it's own {@link module:engine/view/position~Position} instances basing on passed values. + * + * @param {module:engine/view/position~Position} start Start position. + * @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at `start` position. + * @returns {module:engine/view/range~Range} + */ + createRange( start, end ) { + return new Range( start, end ); + } + + /** + * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it. + * + * @param {module:engine/view/item~Item} item + * @returns {module:engine/view/range~Range} + */ + createRangeOn( item ) { + return Range._createOn( item ); + } + + /** + * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of + * that element and ends after the last child of that element. + * + * @param {module:engine/view/element~Element} element Element which is a parent for the range. + * @returns {module:engine/view/range~Range} + */ + createRangeIn( element ) { + return Range._createIn( element ); + } + + /** + * Creates a new {@link module:engine/view/selection~Selection} instance. + * + * // Creates empty selection without ranges. + * const selection = writer.createSelection(); + * + * // Creates selection at the given range. + * const range = writer.createRange( start, end ); + * const selection = writer.createSelection( range ); + * + * // Creates selection at the given ranges + * const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ]; + * const selection = writer.createSelection( ranges ); + * + * // Creates selection from the other selection. + * const otherSelection = writer.createSelection(); + * const selection = writer.createSelection( otherSelection ); + * + * // Creates selection from the document selection. + * const selection = writer.createSelection( editor.editing.view.document.selection ); + * + * // Creates selection at the given position. + * const position = writer.createPositionFromPath( root, path ); + * const selection = writer.createSelection( position ); + * + * // Creates collapsed selection at the position of given item and offset. + * const paragraph = writer.createContainerElement( 'paragraph' ); + * const selection = writer.createSelection( paragraph, offset ); + * + * // Creates a range inside an {@link module:engine/view/element~Element element} which starts before the + * // first child of that element and ends after the last child of that element. + * const selection = writer.createSelection( paragraph, 'in' ); + * + * // Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends + * // just after the item. + * const selection = writer.createSelection( paragraph, 'on' ); + * + * `Selection`'s constructor allow passing additional options (`backward`, `fake` and `label`) as the last argument. + * + * // Creates backward selection. + * const selection = writer.createSelection( range, { backward: true } ); + * + * Fake selection does not render as browser native selection over selected elements and is hidden to the user. + * This way, no native selection UI artifacts are displayed to the user and selection over elements can be + * represented in other way, for example by applying proper CSS class. + * + * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM + * (and be properly handled by screen readers). + * + * // Creates fake selection with label. + * const selection = writer.createSelection( range, { fake: true, label: 'foo' } ); + * + * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection| + * module:engine/view/position~Position|Iterable.|module:engine/view/range~Range| + * module:engine/view/item~Item|null} [selectable=null] + * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`. + * @param {Object} [options] + * @param {Boolean} [options.backward] Sets this selection instance to be backward. + * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`. + * @param {String} [options.label] Label for the fake selection. + * @returns {module:engine/view/selection~Selection} + */ + createSelection( selectable, placeOrOffset, options ) { + return new Selection( selectable, placeOrOffset, options ); + } } diff --git a/src/view/view.js b/src/view/view.js index 7e8c9d47a..a8d21359a 100644 --- a/src/view/view.js +++ b/src/view/view.js @@ -11,6 +11,9 @@ import Document from './document'; import DowncastWriter from './downcastwriter'; import Renderer from './renderer'; import DomConverter from './domconverter'; +import Position from './position'; +import Range from './range'; +import Selection from './selection'; import MutationObserver from './observer/mutationobserver'; import KeyObserver from './observer/keyobserver'; @@ -394,6 +397,147 @@ export default class View { this.stopListening(); } + /** + * Creates position at the given location. The location can be specified as: + * + * * a {@link module:engine/view/position~Position position}, + * * parent element and offset (offset defaults to `0`), + * * parent element and `'end'` (sets position at the end of that element), + * * {@link module:engine/view/item~Item view item} and `'before'` or `'after'` (sets position before or after given view item). + * + * This method is a shortcut to other constructors such as: + * + * * {@link #createPositionBefore}, + * * {@link #createPositionAfter}, + * + * @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition + * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when + * first parameter is a {@link module:engine/view/item~Item view item}. + */ + createPositionAt( itemOrPosition, offset ) { + return Position._createAt( itemOrPosition, offset ); + } + + /** + * Creates a new position after given view item. + * + * @param {module:engine/view/item~Item} item View item after which the position should be located. + * @returns {module:engine/view/position~Position} + */ + createPositionAfter( item ) { + return Position._createAfter( item ); + } + + /** + * Creates a new position before given view item. + * + * @param {module:engine/view/item~Item} item View item before which the position should be located. + * @returns {module:engine/view/position~Position} + */ + createPositionBefore( item ) { + return Position._createBefore( item ); + } + + /** + * Creates a range spanning from `start` position to `end` position. + * + * **Note:** This factory method creates it's own {@link module:engine/view/position~Position} instances basing on passed values. + * + * @param {module:engine/view/position~Position} start Start position. + * @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at `start` position. + * @returns {module:engine/view/range~Range} + */ + createRange( start, end ) { + return new Range( start, end ); + } + + /** + * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it. + * + * @param {module:engine/view/item~Item} item + * @returns {module:engine/view/range~Range} + */ + createRangeOn( item ) { + return Range._createOn( item ); + } + + /** + * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of + * that element and ends after the last child of that element. + * + * @param {module:engine/view/element~Element} element Element which is a parent for the range. + * @returns {module:engine/view/range~Range} + */ + createRangeIn( element ) { + return Range._createIn( element ); + } + + /** + Creates new {@link module:engine/view/selection~Selection} instance. + * + * // Creates empty selection without ranges. + * const selection = view.createSelection(); + * + * // Creates selection at the given range. + * const range = view.createRange( start, end ); + * const selection = view.createSelection( range ); + * + * // Creates selection at the given ranges + * const ranges = [ view.createRange( start1, end2 ), view.createRange( star2, end2 ) ]; + * const selection = view.createSelection( ranges ); + * + * // Creates selection from the other selection. + * const otherSelection = view.createSelection(); + * const selection = view.createSelection( otherSelection ); + * + * // Creates selection from the document selection. + * const selection = view.createSelection( editor.editing.view.document.selection ); + * + * // Creates selection at the given position. + * const position = view.createPositionFromPath( root, path ); + * const selection = view.createSelection( position ); + * + * // Creates collapsed selection at the position of given item and offset. + * const paragraph = view.createContainerElement( 'paragraph' ); + * const selection = view.createSelection( paragraph, offset ); + * + * // Creates a range inside an {@link module:engine/view/element~Element element} which starts before the + * // first child of that element and ends after the last child of that element. + * const selection = view.createSelection( paragraph, 'in' ); + * + * // Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends + * // just after the item. + * const selection = view.createSelection( paragraph, 'on' ); + * + * `Selection`'s factory method allow passing additional options (`backward`, `fake` and `label`) as the last argument. + * + * // Creates backward selection. + * const selection = view.createSelection( range, { backward: true } ); + * + * Fake selection does not render as browser native selection over selected elements and is hidden to the user. + * This way, no native selection UI artifacts are displayed to the user and selection over elements can be + * represented in other way, for example by applying proper CSS class. + * + * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM + * (and be properly handled by screen readers). + * + * // Creates fake selection with label. + * const selection = view.createSelection( range, { fake: true, label: 'foo' } ); + * + * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection| + * module:engine/view/position~Position|Iterable.|module:engine/view/range~Range| + * module:engine/view/item~Item|null} [selectable=null] + * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`. + * @param {Object} [options] + * @param {Boolean} [options.backward] Sets this selection instance to be backward. + * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`. + * @param {String} [options.label] Label for the fake selection. + * @returns {module:engine/view/selection~Selection} + */ + createSelection( selectable, placeOrOffset, options ) { + return new Selection( selectable, placeOrOffset, options ); + } + /** * Renders all changes. In order to avoid triggering the observers (e.g. mutations) all observers are disabled * before rendering and re-enabled after that. diff --git a/tests/controller/datacontroller.js b/tests/controller/datacontroller.js index f1c608e8c..b2e82969e 100644 --- a/tests/controller/datacontroller.js +++ b/tests/controller/datacontroller.js @@ -407,7 +407,7 @@ describe( 'DataController', () => { model.change( writer => { writer.insert( modelElement, modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 0 ), writer.createPositionAt( modelRoot, 1 ) ); writer.addMarker( 'marker:a', { range, usingOperation: true } ); } ); @@ -430,8 +430,8 @@ describe( 'DataController', () => { model.change( writer => { writer.insert( modelElement, modelRoot, 0 ); - const rangeA = ModelRange.createFromParentsAndOffsets( modelP1, 1, modelP1, 3 ); - const rangeB = ModelRange.createFromParentsAndOffsets( modelP2, 0, modelP2, 2 ); + const rangeA = writer.createRange( writer.createPositionAt( modelP1, 1 ), writer.createPositionAt( modelP1, 3 ) ); + const rangeB = writer.createRange( writer.createPositionAt( modelP2, 0 ), writer.createPositionAt( modelP2, 2 ) ); writer.addMarker( 'marker:a', { range: rangeA, usingOperation: true } ); writer.addMarker( 'marker:b', { range: rangeB, usingOperation: true } ); @@ -463,8 +463,8 @@ describe( 'DataController', () => { const firstModelElement = modelDocumentFragment.getChild( 0 ); const firstViewElement = viewDocumentFragment.getChild( 0 ); - const modelRange = ModelRange.createOn( firstModelElement ); - const viewRange = ViewRange.createOn( firstViewElement ); + const modelRange = ModelRange._createOn( firstModelElement ); + const viewRange = ViewRange._createOn( firstViewElement ); const mappedModelRange = data.mapper.toModelRange( viewRange ); const mappedViewRange = data.mapper.toViewRange( modelRange ); diff --git a/tests/controller/editingcontroller.js b/tests/controller/editingcontroller.js index 701fd00ac..8a67ed62a 100644 --- a/tests/controller/editingcontroller.js +++ b/tests/controller/editingcontroller.js @@ -114,9 +114,10 @@ describe( 'EditingController', () => { model.change( writer => { writer.insert( modelData, model.document.getRoot() ); - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 0 ), 1, modelRoot.getChild( 0 ), 1 ) - ); + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ) + ) ); } ); } ); @@ -136,9 +137,10 @@ describe( 'EditingController', () => { model.change( writer => { writer.split( model.document.selection.getFirstPosition() ); - writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 1 ), 0, modelRoot.getChild( 1 ), 0 ) - ); + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 1 ), 0 ), + writer.createPositionAt( modelRoot.getChild( 1 ), 0 ) + ) ); } ); expect( getViewData( editing.view ) ).to.equal( '

f

{}oo

bar

' ); @@ -157,12 +159,13 @@ describe( 'EditingController', () => { it( 'should convert delete', () => { model.change( writer => { writer.remove( - ModelRange.createFromPositionAndShift( model.document.selection.getFirstPosition(), 1 ) + ModelRange._createFromPositionAndShift( model.document.selection.getFirstPosition(), 1 ) ); - writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 1, modelRoot.getChild( 0 ), 1 ) - ); + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ) + ) ); } ); expect( getViewData( editing.view ) ).to.equal( '

f{}o

bar

' ); @@ -195,9 +198,10 @@ describe( 'EditingController', () => { it( 'should convert collapsed selection', () => { model.change( writer => { - writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 2 ), 1, modelRoot.getChild( 2 ), 1 ) - ); + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 2 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 2 ), 1 ) + ) ); } ); expect( getViewData( editing.view ) ).to.equal( '

foo

b{}ar

' ); @@ -205,9 +209,10 @@ describe( 'EditingController', () => { it( 'should convert not collapsed selection', () => { model.change( writer => { - writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 2 ), 1, modelRoot.getChild( 2 ), 2 ) - ); + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 2 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 2 ), 2 ) + ) ); } ); expect( getViewData( editing.view ) ).to.equal( '

foo

b{a}r

' ); @@ -215,17 +220,19 @@ describe( 'EditingController', () => { it( 'should clear previous selection', () => { model.change( writer => { - writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 2 ), 1, modelRoot.getChild( 2 ), 1 ) - ); + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 2 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 2 ), 1 ) + ) ); } ); expect( getViewData( editing.view ) ).to.equal( '

foo

b{}ar

' ); model.change( writer => { - writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 2 ), 2, modelRoot.getChild( 2 ), 2 ) - ); + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 2 ), 2 ), + writer.createPositionAt( modelRoot.getChild( 2 ), 2 ) + ) ); } ); expect( getViewData( editing.view ) ).to.equal( '

foo

ba{}r

' ); diff --git a/tests/conversion/conversion.js b/tests/conversion/conversion.js index 01a341b70..948c08a01 100644 --- a/tests/conversion/conversion.js +++ b/tests/conversion/conversion.js @@ -13,7 +13,6 @@ import { convertText, convertToModelFragment } from '../../src/conversion/upcast import EditingController from '../../src/controller/editingcontroller'; import Model from '../../src/model/model'; -import ModelRange from '../../src/model/range'; import { stringify as viewStringify, parse as viewParse } from '../../src/dev-utils/view'; import { stringify as modelStringify } from '../../src/dev-utils/model'; @@ -644,7 +643,10 @@ describe( 'Conversion', () => { } ); model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, modelRoot.maxOffset ) ); + writer.remove( writer.createRange( + writer.createPositionAt( modelRoot, 0 ), + writer.createPositionAt( modelRoot, modelRoot.maxOffset ) ) + ); writer.insert( convertedModel, modelRoot, 0 ); } ); } diff --git a/tests/conversion/downcast-converters.js b/tests/conversion/downcast-converters.js index 3a7db166c..0efc408cb 100644 --- a/tests/conversion/downcast-converters.js +++ b/tests/conversion/downcast-converters.js @@ -10,8 +10,6 @@ import Conversion from '../../src/conversion/conversion'; import Model from '../../src/model/model'; import ModelElement from '../../src/model/element'; import ModelText from '../../src/model/text'; -import ModelRange from '../../src/model/range'; -import ModelPosition from '../../src/model/position'; import ViewElement from '../../src/view/element'; import ViewAttributeElement from '../../src/view/attributeelement'; @@ -473,7 +471,7 @@ describe( 'downcast-helpers', () => { model.change( writer => { writer.insertText( 'foo', modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 2 ) ); writer.addMarker( 'search', { range, usingOperation: false } ); } ); @@ -488,7 +486,7 @@ describe( 'downcast-helpers', () => { model.change( writer => { writer.insertText( 'foo', modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 2 ) ); writer.addMarker( 'search', { range, usingOperation: false } ); } ); @@ -510,7 +508,7 @@ describe( 'downcast-helpers', () => { model.change( writer => { writer.insertText( 'foo', modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 2 ) ); writer.addMarker( 'search', { range, usingOperation: false } ); } ); @@ -529,7 +527,7 @@ describe( 'downcast-helpers', () => { model.change( writer => { writer.insertText( 'foo', modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 2 ) ); writer.addMarker( 'search', { range, usingOperation: false } ); } ); @@ -545,7 +543,7 @@ describe( 'downcast-helpers', () => { model.change( writer => { writer.insertText( 'foo', modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 0 ), writer.createPositionAt( modelRoot, 3 ) ); writer.addMarker( 'comment', { range, usingOperation: false } ); } ); @@ -560,7 +558,7 @@ describe( 'downcast-helpers', () => { model.change( writer => { writer.insertText( 'foo', modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 0 ), writer.createPositionAt( modelRoot, 3 ) ); writer.addMarker( 'comment', { range, usingOperation: false } ); } ); @@ -583,7 +581,7 @@ describe( 'downcast-helpers', () => { model.change( writer => { writer.insertText( 'foo', modelRoot, 0 ); - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 0 ), writer.createPositionAt( modelRoot, 3 ) ); writer.addMarker( 'comment:abc', { range, usingOperation: false } ); } ); @@ -622,7 +620,7 @@ describe( 'downcast-converters', () => { dispatcher.on( 'attribute:class', changeAttribute() ); - modelRootStart = ModelPosition.createAt( modelRoot, 0 ); + modelRootStart = model.createPositionAt( modelRoot, 0 ); } ); function viewAttributesToString( item ) { @@ -815,7 +813,7 @@ describe( 'downcast-converters', () => { expect( viewToString( viewRoot ) ).to.equal( '

foobar

' ); model.change( writer => { - writer.removeAttribute( 'bold', ModelRange.createIn( modelElement ) ); + writer.removeAttribute( 'bold', writer.createRangeIn( modelElement ) ); } ); expect( viewToString( viewRoot ) ).to.equal( '

foobar

' ); @@ -839,7 +837,7 @@ describe( 'downcast-converters', () => { expect( viewToString( viewRoot ) ).to.equal( '

foobar

' ); model.change( writer => { - writer.removeAttribute( 'style', ModelRange.createIn( modelElement ) ); + writer.removeAttribute( 'style', writer.createRangeIn( modelElement ) ); } ); expect( viewToString( viewRoot ) ).to.equal( '

foobar

' ); @@ -866,7 +864,7 @@ describe( 'downcast-converters', () => { // Set new attribute on old link but also on non-linked characters. model.change( writer => { - writer.setAttribute( 'link', 'http://foobar.com', ModelRange.createIn( modelElement ) ); + writer.setAttribute( 'link', 'http://foobar.com', writer.createRangeIn( modelElement ) ); } ); expect( viewToString( viewRoot ) ).to.equal( '' ); @@ -885,7 +883,7 @@ describe( 'downcast-converters', () => { expect( viewToString( viewRoot ) ).to.equal( '

நிலைக்கு

' ); model.change( writer => { - writer.removeAttribute( 'bold', ModelRange.createIn( modelElement ) ); + writer.removeAttribute( 'bold', writer.createRangeIn( modelElement ) ); } ); expect( viewToString( viewRoot ) ).to.equal( '

நிலைக்கு

' ); @@ -945,7 +943,7 @@ describe( 'downcast-converters', () => { describe( 'collapsed range', () => { beforeEach( () => { - range = ModelRange.createFromParentsAndOffsets( modelElement, 3, modelElement, 3 ); + range = model.createRange( model.createPositionAt( modelElement, 3 ), model.createPositionAt( modelElement, 3 ) ); } ); it( 'should insert and remove ui element', () => { @@ -1006,7 +1004,7 @@ describe( 'downcast-converters', () => { describe( 'non-collapsed range', () => { beforeEach( () => { - range = ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 5 ); + range = model.createRange( model.createPositionAt( modelElement, 2 ), model.createPositionAt( modelElement, 5 ) ); } ); it( 'should insert and remove ui element - element as a creator', () => { @@ -1106,7 +1104,9 @@ describe( 'downcast-converters', () => { } ); model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) ); + writer.remove( + writer.createRange( writer.createPositionAt( modelElement, 2 ), writer.createPositionAt( modelElement, 4 ) ) + ); } ); expect( viewToString( viewRoot ) ).to.equal( '

foar

' ); @@ -1122,7 +1122,9 @@ describe( 'downcast-converters', () => { } ); model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelElement, 2, modelElement, 4 ) ); + writer.remove( + writer.createRange( writer.createPositionAt( modelElement, 2 ), writer.createPositionAt( modelElement, 4 ) ) + ); } ); expect( viewToString( viewRoot ) ).to.equal( '

foobar

' ); @@ -1136,7 +1138,9 @@ describe( 'downcast-converters', () => { } ); model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelElement, 0, modelElement, 6 ) ); + writer.remove( + writer.createRange( writer.createPositionAt( modelElement, 0 ), writer.createPositionAt( modelElement, 6 ) ) + ); } ); expect( viewToString( viewRoot ) ).to.equal( '

கு

' ); @@ -1152,14 +1156,18 @@ describe( 'downcast-converters', () => { // Remove 'b'. model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelRoot, 3, modelRoot, 4 ) ); + writer.remove( + writer.createRange( writer.createPositionAt( modelRoot, 3 ), writer.createPositionAt( modelRoot, 4 ) ) + ); } ); expect( viewToString( viewRoot ) ).to.equal( '
fozar
' ); // Remove 'z'. model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelRoot, 2, modelRoot, 3 ) ); + writer.remove( + writer.createRange( writer.createPositionAt( modelRoot, 2 ), writer.createPositionAt( modelRoot, 3 ) ) + ); } ); expect( viewToString( viewRoot ) ).to.equal( '
foar
' ); @@ -1175,7 +1183,9 @@ describe( 'downcast-converters', () => { // Remove 'zb'. model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelRoot, 2, modelRoot, 4 ) ); + writer.remove( + writer.createRange( writer.createPositionAt( modelRoot, 2 ), writer.createPositionAt( modelRoot, 4 ) ) + ); } ); expect( viewToString( viewRoot ) ).to.equal( '
foar
' ); @@ -1250,7 +1260,7 @@ describe( 'downcast-converters', () => { // Remove second paragraph element. model.change( writer => { - writer.remove( ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ) ); + writer.remove( writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 2 ) ) ); } ); expect( viewToString( viewRoot ) ).to.equal( '

' ); @@ -1290,7 +1300,7 @@ describe( 'downcast-converters', () => { writer.insert( [ modelElement1, modelElement2 ], modelRootStart ); } ); - markerRange = ModelRange.createIn( modelRoot ); + markerRange = model.createRangeIn( modelRoot ); } ); it( 'should wrap and unwrap text nodes', () => { @@ -1378,7 +1388,7 @@ describe( 'downcast-converters', () => { dispatcher.on( 'addMarker:marker', highlightElement( descriptor ), { priority: 'high' } ); dispatcher.on( 'removeMarker:marker', removeHighlight( descriptor ), { priority: 'high' } ); - markerRange = ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 0 ); + markerRange = model.createRange( model.createPositionAt( modelRoot, 0 ), model.createPositionAt( modelRoot, 0 ) ); model.change( writer => { writer.addMarker( 'marker', { range: markerRange, usingOperation: false } ); @@ -1410,7 +1420,7 @@ describe( 'downcast-converters', () => { const p2 = modelRoot.getChild( 1 ); model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( p1, 0, p1, 3 ); + const range = writer.createRange( writer.createPositionAt( p1, 0 ), writer.createPositionAt( p1, 3 ) ); writer.addMarker( 'markerFoo', { range, usingOperation: false } ); } ); @@ -1424,7 +1434,7 @@ describe( 'downcast-converters', () => { ); model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( p1, 1, p2, 2 ); + const range = writer.createRange( writer.createPositionAt( p1, 1 ), writer.createPositionAt( p2, 2 ) ); writer.addMarker( 'markerBar', { range, usingOperation: false } ); } ); @@ -1444,7 +1454,7 @@ describe( 'downcast-converters', () => { ); model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( p1, 2, p2, 3 ); + const range = writer.createRange( writer.createPositionAt( p1, 2 ), writer.createPositionAt( p2, 3 ) ); writer.addMarker( 'markerXyz', { range, usingOperation: false } ); } ); @@ -1516,7 +1526,7 @@ describe( 'downcast-converters', () => { const p1 = modelRoot.getChild( 0 ); const p2 = modelRoot.getChild( 1 ); - const markerRange = ModelRange.createFromParentsAndOffsets( p1, 3, p2, 0 ); + const markerRange = model.createRange( model.createPositionAt( p1, 3 ), model.createPositionAt( p2, 0 ) ); model.change( writer => { writer.addMarker( 'marker', { range: markerRange, usingOperation: false } ); @@ -1564,7 +1574,7 @@ describe( 'downcast-converters', () => { writer.insert( modelElement, modelRootStart ); } ); - markerRange = ModelRange.createOn( modelElement ); + markerRange = model.createRangeOn( modelElement ); dispatcher.on( 'addMarker:marker', highlightText( highlightDescriptor ) ); dispatcher.on( 'addMarker:marker', highlightElement( highlightDescriptor ) ); diff --git a/tests/conversion/downcast-selection-converters.js b/tests/conversion/downcast-selection-converters.js index 2a0def3f1..1dc9ee05d 100644 --- a/tests/conversion/downcast-selection-converters.js +++ b/tests/conversion/downcast-selection-converters.js @@ -4,9 +4,6 @@ */ import Model from '../../src/model/model'; -import ModelElement from '../../src/model/element'; -import ModelRange from '../../src/model/range'; -import ModelPosition from '../../src/model/position'; import View from '../../src/view/view'; import ViewUIElement from '../../src/view/uielement'; @@ -197,9 +194,9 @@ describe( 'downcast-selection-converters', () => { setModelData( model, 'fo<$text bold="true">obar' ); model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 5 ) ); marker = writer.addMarker( 'marker', { range, usingOperation: false } ); - writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) ); + writer.setSelection( modelRoot, 3 ); } ); // Remove view children manually (without firing additional conversion). @@ -207,7 +204,7 @@ describe( 'downcast-selection-converters', () => { // Convert model to view. view.change( writer => { - dispatcher.convertInsert( ModelRange.createIn( modelRoot ), writer ); + dispatcher.convertInsert( model.createRangeIn( modelRoot ), writer ); dispatcher.convertMarkerAdd( marker.name, marker.getRange(), writer ); dispatcher.convertSelection( docSelection, model.markers, writer ); } ); @@ -222,9 +219,9 @@ describe( 'downcast-selection-converters', () => { setModelData( model, 'fo<$text bold="true">obar' ); model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 5 ) ); marker = writer.addMarker( 'marker', { range, usingOperation: false } ); - writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) ); + writer.setSelection( modelRoot, 3 ); writer.removeSelectionAttribute( 'bold' ); } ); @@ -233,7 +230,7 @@ describe( 'downcast-selection-converters', () => { // Convert model to view. view.change( writer => { - dispatcher.convertInsert( ModelRange.createIn( modelRoot ), writer ); + dispatcher.convertInsert( model.createRangeIn( modelRoot ), writer ); dispatcher.convertMarkerAdd( marker.name, marker.getRange(), writer ); dispatcher.convertSelection( docSelection, model.markers, writer ); } ); @@ -251,9 +248,9 @@ describe( 'downcast-selection-converters', () => { setModelData( model, 'foobar' ); model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 5 ) ); marker = writer.addMarker( 'marker2', { range, usingOperation: false } ); - writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) ); + writer.setSelection( modelRoot, 3 ); } ); // Remove view children manually (without firing additional conversion). @@ -261,7 +258,7 @@ describe( 'downcast-selection-converters', () => { // Convert model to view. view.change( writer => { - dispatcher.convertInsert( ModelRange.createIn( modelRoot ), writer ); + dispatcher.convertInsert( model.createRangeIn( modelRoot ), writer ); dispatcher.convertMarkerAdd( marker.name, marker.getRange(), writer ); dispatcher.convertSelection( docSelection, model.markers, writer ); } ); @@ -277,9 +274,9 @@ describe( 'downcast-selection-converters', () => { setModelData( model, 'foobar' ); model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 5 ); + const range = writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 5 ) ); marker = writer.addMarker( 'marker3', { range, usingOperation: false } ); - writer.setSelection( new ModelRange( ModelPosition.createAt( modelRoot, 3 ) ) ); + writer.setSelection( modelRoot, 3 ); } ); // Remove view children manually (without firing additional conversion). @@ -287,7 +284,7 @@ describe( 'downcast-selection-converters', () => { // Convert model to view. view.change( writer => { - dispatcher.convertInsert( ModelRange.createIn( modelRoot ), writer ); + dispatcher.convertInsert( model.createRangeIn( modelRoot ), writer ); dispatcher.convertMarkerAdd( marker.name, marker.getRange(), writer ); dispatcher.convertSelection( docSelection, model.markers, writer ); } ); @@ -308,7 +305,7 @@ describe( 'downcast-selection-converters', () => { ] ); model.change( writer => { - writer.setSelection( new ModelRange( new ModelPosition( modelRoot, [ 0 ] ) ) ); + writer.setSelection( writer.createRange( writer.createPositionFromPath( modelRoot, [ 0 ] ) ) ); writer.setSelectionAttribute( 'bold', true ); } ); @@ -327,13 +324,13 @@ describe( 'downcast-selection-converters', () => { setModelData( model, 'x' ); model.change( writer => { - writer.setSelection( new ModelRange( new ModelPosition( modelRoot, [ 1 ] ) ) ); + writer.setSelection( writer.createRange( writer.createPositionFromPath( modelRoot, [ 1 ] ) ) ); writer.setSelectionAttribute( 'bold', true ); } ); // Convert model to view. view.change( writer => { - dispatcher.convertInsert( ModelRange.createIn( modelRoot ), writer ); + dispatcher.convertInsert( model.createRangeIn( modelRoot ), writer ); // Add ui element to view. const uiElement = new ViewUIElement( 'span' ); @@ -352,13 +349,13 @@ describe( 'downcast-selection-converters', () => { setModelData( model, '<$text bold="true">xy' ); model.change( writer => { - writer.setSelection( new ModelRange( new ModelPosition( modelRoot, [ 1 ] ) ) ); + writer.setSelection( writer.createRange( writer.createPositionFromPath( modelRoot, [ 1 ] ) ) ); writer.setSelectionAttribute( 'bold', true ); } ); // Convert model to view. view.change( writer => { - dispatcher.convertInsert( ModelRange.createIn( modelRoot ), writer ); + dispatcher.convertInsert( model.createRangeIn( modelRoot ), writer ); // Add ui element to view. const uiElement = new ViewUIElement( 'span' ); @@ -439,7 +436,7 @@ describe( 'downcast-selection-converters', () => { ); view.change( writer => { - const modelRange = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 1 ); + const modelRange = model.createRange( model.createPositionAt( modelRoot, 1 ), model.createPositionAt( modelRoot, 1 ) ); model.change( writer => { writer.setSelection( modelRange ); } ); @@ -465,7 +462,7 @@ describe( 'downcast-selection-converters', () => { // Remove manually. writer.mergeAttributes( viewSelection.getFirstPosition() ); - const modelRange = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 1 ); + const modelRange = model.createRange( model.createPositionAt( modelRoot, 1 ), model.createPositionAt( modelRoot, 1 ) ); model.change( writer => { writer.setSelection( modelRange ); } ); @@ -480,7 +477,7 @@ describe( 'downcast-selection-converters', () => { } ); it( 'should clear fake selection', () => { - const modelRange = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 1 ); + const modelRange = model.createRange( model.createPositionAt( modelRoot, 1 ), model.createPositionAt( modelRoot, 1 ) ); view.change( writer => { writer.setSelection( modelRange, { fake: true } ); @@ -521,7 +518,7 @@ describe( 'downcast-selection-converters', () => { for ( const range of selection.getRanges() ) { const node = range.start.parent; - if ( node instanceof ModelElement && node.name == 'td' ) { + if ( !!node && node.is( 'td' ) ) { conversionApi.consumable.consume( selection, 'selection' ); const viewNode = conversionApi.mapper.toViewElement( node ); @@ -571,12 +568,12 @@ describe( 'downcast-selection-converters', () => { const startPath = typeof selectionPaths[ 0 ] == 'number' ? [ selectionPaths[ 0 ] ] : selectionPaths[ 0 ]; const endPath = typeof selectionPaths[ 1 ] == 'number' ? [ selectionPaths[ 1 ] ] : selectionPaths[ 1 ]; - const startPos = new ModelPosition( modelRoot, startPath ); - const endPos = new ModelPosition( modelRoot, endPath ); + const startPos = model.createPositionFromPath( modelRoot, startPath ); + const endPos = model.createPositionFromPath( modelRoot, endPath ); const isBackward = selectionPaths[ 2 ] === 'backward'; model.change( writer => { - writer.setSelection( new ModelRange( startPos, endPos ), { backward: isBackward } ); + writer.setSelection( writer.createRange( startPos, endPos ), { backward: isBackward } ); // And add or remove passed attributes. for ( const key in selectionAttributes ) { @@ -595,7 +592,7 @@ describe( 'downcast-selection-converters', () => { // Convert model to view. view.change( writer => { - dispatcher.convertInsert( ModelRange.createIn( modelRoot ), writer ); + dispatcher.convertInsert( model.createRangeIn( modelRoot ), writer ); dispatcher.convertSelection( docSelection, model.markers, writer ); } ); diff --git a/tests/conversion/downcastdispatcher.js b/tests/conversion/downcastdispatcher.js index 9012cee0f..05568471d 100644 --- a/tests/conversion/downcastdispatcher.js +++ b/tests/conversion/downcastdispatcher.js @@ -8,7 +8,6 @@ import Model from '../../src/model/model'; import ModelText from '../../src/model/text'; import ModelElement from '../../src/model/element'; import ModelRange from '../../src/model/range'; -import ModelPosition from '../../src/model/position'; import View from '../../src/view/view'; import ViewContainerElement from '../../src/view/containerelement'; @@ -43,8 +42,8 @@ describe( 'DowncastDispatcher', () => { it( 'should call convertInsert for insert change', () => { sinon.stub( dispatcher, 'convertInsert' ); - const position = new ModelPosition( root, [ 0 ] ); - const range = ModelRange.createFromPositionAndShift( position, 1 ); + const position = model.createPositionFromPath( root, [ 0 ] ); + const range = ModelRange._createFromPositionAndShift( position, 1 ); differStub.getChanges = () => [ { type: 'insert', position, length: 1 } ]; @@ -59,7 +58,7 @@ describe( 'DowncastDispatcher', () => { it( 'should call convertRemove for remove change', () => { sinon.stub( dispatcher, 'convertRemove' ); - const position = new ModelPosition( root, [ 0 ] ); + const position = model.createPositionFromPath( root, [ 0 ] ); differStub.getChanges = () => [ { type: 'remove', position, length: 2, name: '$text' } ]; @@ -73,8 +72,8 @@ describe( 'DowncastDispatcher', () => { it( 'should call convertAttribute for attribute change', () => { sinon.stub( dispatcher, 'convertAttribute' ); - const position = new ModelPosition( root, [ 0 ] ); - const range = ModelRange.createFromPositionAndShift( position, 1 ); + const position = model.createPositionFromPath( root, [ 0 ] ); + const range = ModelRange._createFromPositionAndShift( position, 1 ); differStub.getChanges = () => [ { type: 'attribute', position, range, attributeKey: 'key', attributeOldValue: null, attributeNewValue: 'foo' } @@ -92,8 +91,8 @@ describe( 'DowncastDispatcher', () => { sinon.stub( dispatcher, 'convertRemove' ); sinon.stub( dispatcher, 'convertAttribute' ); - const position = new ModelPosition( root, [ 0 ] ); - const range = ModelRange.createFromPositionAndShift( position, 1 ); + const position = model.createPositionFromPath( root, [ 0 ] ); + const range = ModelRange._createFromPositionAndShift( position, 1 ); differStub.getChanges = () => [ { type: 'insert', position, length: 1 }, @@ -114,8 +113,8 @@ describe( 'DowncastDispatcher', () => { it( 'should call convertMarkerAdd when markers are added', () => { sinon.stub( dispatcher, 'convertMarkerAdd' ); - const fooRange = ModelRange.createFromParentsAndOffsets( root, 0, root, 1 ); - const barRange = ModelRange.createFromParentsAndOffsets( root, 3, root, 6 ); + const fooRange = model.createRange( model.createPositionAt( root, 0 ), model.createPositionAt( root, 1 ) ); + const barRange = model.createRange( model.createPositionAt( root, 3 ), model.createPositionAt( root, 6 ) ); differStub.getMarkersToAdd = () => [ { name: 'foo', range: fooRange }, @@ -133,8 +132,8 @@ describe( 'DowncastDispatcher', () => { it( 'should call convertMarkerRemove when markers are removed', () => { sinon.stub( dispatcher, 'convertMarkerRemove' ); - const fooRange = ModelRange.createFromParentsAndOffsets( root, 0, root, 1 ); - const barRange = ModelRange.createFromParentsAndOffsets( root, 3, root, 6 ); + const fooRange = model.createRange( model.createPositionAt( root, 0 ), model.createPositionAt( root, 1 ) ); + const barRange = model.createRange( model.createPositionAt( root, 3 ), model.createPositionAt( root, 6 ) ); differStub.getMarkersToRemove = () => [ { name: 'foo', range: fooRange }, @@ -159,7 +158,7 @@ describe( 'DowncastDispatcher', () => { new ModelElement( 'paragraph', { class: 'nice' }, new ModelText( 'xx', { italic: true } ) ) ] ); - const range = ModelRange.createIn( root ); + const range = model.createRangeIn( root ); const loggedEvents = []; // We will check everything connected with insert event: @@ -219,7 +218,7 @@ describe( 'DowncastDispatcher', () => { conversionApi.consumable.consume( data.item, 'attribute:bold' ); } ); - const range = ModelRange.createIn( root ); + const range = model.createRangeIn( root ); dispatcher.convertInsert( range ); @@ -242,7 +241,7 @@ describe( 'DowncastDispatcher', () => { loggedEvents.push( log ); } ); - dispatcher.convertRemove( ModelPosition.createFromParentAndOffset( root, 3 ), 3, '$text' ); + dispatcher.convertRemove( model.createPositionAt( root, 3 ), 3, '$text' ); expect( loggedEvents ).to.deep.equal( [ 'remove:3:3' ] ); } ); @@ -255,8 +254,8 @@ describe( 'DowncastDispatcher', () => { root._appendChild( new ModelText( 'foobar' ) ); model.change( writer => { writer.setSelection( [ - new ModelRange( new ModelPosition( root, [ 1 ] ), new ModelPosition( root, [ 3 ] ) ), - new ModelRange( new ModelPosition( root, [ 4 ] ), new ModelPosition( root, [ 5 ] ) ) + writer.createRange( writer.createPositionFromPath( root, [ 1 ] ), writer.createPositionFromPath( root, [ 3 ] ) ), + writer.createRange( writer.createPositionFromPath( root, [ 4 ] ), writer.createPositionFromPath( root, [ 5 ] ) ) ] ); } ); } ); @@ -274,8 +273,10 @@ describe( 'DowncastDispatcher', () => { it( 'should prepare correct list of consumable values', () => { model.change( writer => { - writer.setAttribute( 'bold', true, ModelRange.createIn( root ) ); - writer.setAttribute( 'italic', true, ModelRange.createFromParentsAndOffsets( root, 4, root, 5 ) ); + writer.setAttribute( 'bold', true, writer.createRangeIn( root ) ); + writer.setAttribute( 'italic', true, + writer.createRange( writer.createPositionAt( root, 4 ), writer.createPositionAt( root, 5 ) ) + ); } ); dispatcher.on( 'selection', ( evt, data, conversionApi ) => { @@ -289,8 +290,10 @@ describe( 'DowncastDispatcher', () => { it( 'should not fire attributes events for non-collapsed selection', () => { model.change( writer => { - writer.setAttribute( 'bold', true, ModelRange.createIn( root ) ); - writer.setAttribute( 'italic', true, ModelRange.createFromParentsAndOffsets( root, 4, root, 5 ) ); + writer.setAttribute( 'bold', true, writer.createRangeIn( root ) ); + writer.setAttribute( 'italic', true, + writer.createRange( writer.createPositionAt( root, 4 ), writer.createPositionAt( root, 5 ) ) + ); } ); sinon.spy( dispatcher, 'fire' ); @@ -304,12 +307,12 @@ describe( 'DowncastDispatcher', () => { it( 'should fire attributes events for collapsed selection', () => { model.change( writer => { writer.setSelection( - new ModelRange( new ModelPosition( root, [ 2 ] ), new ModelPosition( root, [ 2 ] ) ) + writer.createRange( writer.createPositionFromPath( root, [ 2 ] ), writer.createPositionFromPath( root, [ 2 ] ) ) ); } ); model.change( writer => { - writer.setAttribute( 'bold', true, ModelRange.createIn( root ) ); + writer.setAttribute( 'bold', true, writer.createRangeIn( root ) ); } ); sinon.spy( dispatcher, 'fire' ); @@ -322,13 +325,15 @@ describe( 'DowncastDispatcher', () => { it( 'should not fire attributes events if attribute has been consumed', () => { model.change( writer => { writer.setSelection( - new ModelRange( new ModelPosition( root, [ 2 ] ), new ModelPosition( root, [ 2 ] ) ) + writer.createRange( writer.createPositionFromPath( root, [ 2 ] ), writer.createPositionFromPath( root, [ 2 ] ) ) ); } ); model.change( writer => { - writer.setAttribute( 'bold', true, ModelRange.createIn( root ) ); - writer.setAttribute( 'italic', true, ModelRange.createFromParentsAndOffsets( root, 4, root, 5 ) ); + writer.setAttribute( 'bold', true, writer.createRangeIn( root ) ); + writer.setAttribute( 'italic', true, + writer.createRange( writer.createPositionAt( root, 4 ), writer.createPositionAt( root, 5 ) ) + ); } ); dispatcher.on( 'selection', ( evt, data, conversionApi ) => { @@ -345,9 +350,9 @@ describe( 'DowncastDispatcher', () => { it( 'should fire events for markers for collapsed selection', () => { model.change( writer => { writer.setSelection( - new ModelRange( new ModelPosition( root, [ 1 ] ), new ModelPosition( root, [ 1 ] ) ) + writer.createRange( writer.createPositionFromPath( root, [ 1 ] ), writer.createPositionFromPath( root, [ 1 ] ) ) ); - const range = ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ); + const range = writer.createRange( writer.createPositionAt( root, 0 ), writer.createPositionAt( root, 2 ) ); writer.addMarker( 'name', { range, usingOperation: false } ); } ); @@ -361,7 +366,7 @@ describe( 'DowncastDispatcher', () => { it( 'should not fire events for markers for non-collapsed selection', () => { model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ); + const range = writer.createRange( writer.createPositionAt( root, 0 ), writer.createPositionAt( root, 2 ) ); writer.addMarker( 'name', { range, usingOperation: false } ); } ); @@ -402,9 +407,9 @@ describe( 'DowncastDispatcher', () => { }; model.change( writer => { - const range = ModelRange.createFromParentsAndOffsets( root, 0, root, 1 ); + const range = writer.createRange( writer.createPositionAt( root, 0 ), writer.createPositionAt( root, 1 ) ); writer.addMarker( 'name', { range, usingOperation: false } ); - writer.setSelection( ModelRange.createFromParentsAndOffsets( caption, 1, caption, 1 ) ); + writer.setSelection( caption, 1 ); } ); sinon.spy( dispatcher, 'fire' ); @@ -418,10 +423,10 @@ describe( 'DowncastDispatcher', () => { it( 'should not fire events if information about marker has been consumed', () => { model.change( writer => { writer.setSelection( - new ModelRange( new ModelPosition( root, [ 1 ] ), new ModelPosition( root, [ 1 ] ) ) + writer.createRange( writer.createPositionFromPath( root, [ 1 ] ), writer.createPositionFromPath( root, [ 1 ] ) ) ); - const range = ModelRange.createFromParentsAndOffsets( root, 0, root, 2 ); + const range = writer.createRange( writer.createPositionAt( root, 0 ), writer.createPositionAt( root, 2 ) ); writer.addMarker( 'foo', { range, usingOperation: false } ); writer.addMarker( 'bar', { range, usingOperation: false } ); } ); @@ -448,7 +453,7 @@ describe( 'DowncastDispatcher', () => { element = new ModelElement( 'paragraph', null, [ text ] ); root._appendChild( [ element ] ); - range = ModelRange.createFromParentsAndOffsets( element, 0, element, 4 ); + range = model.createRange( model.createPositionAt( element, 0 ), model.createPositionAt( element, 4 ) ); } ); it( 'should fire addMarker event', () => { @@ -460,7 +465,7 @@ describe( 'DowncastDispatcher', () => { } ); it( 'should not convert marker if it is in graveyard', () => { - const gyRange = ModelRange.createFromParentsAndOffsets( doc.graveyard, 0, doc.graveyard, 0 ); + const gyRange = model.createRange( model.createPositionAt( doc.graveyard, 0 ), model.createPositionAt( doc.graveyard, 0 ) ); sinon.spy( dispatcher, 'fire' ); dispatcher.convertMarkerAdd( 'name', gyRange ); @@ -470,7 +475,7 @@ describe( 'DowncastDispatcher', () => { it( 'should not convert marker if it is not in model root', () => { const element = new ModelElement( 'element', null, new ModelText( 'foo' ) ); - const eleRange = ModelRange.createFromParentsAndOffsets( element, 1, element, 2 ); + const eleRange = model.createRange( model.createPositionAt( element, 1 ), model.createPositionAt( element, 2 ) ); sinon.spy( dispatcher, 'fire' ); dispatcher.convertMarkerAdd( 'name', eleRange ); @@ -479,7 +484,7 @@ describe( 'DowncastDispatcher', () => { } ); it( 'should fire conversion for each item in the range', () => { - range = ModelRange.createIn( root ); + range = model.createRangeIn( root ); const items = []; @@ -498,7 +503,7 @@ describe( 'DowncastDispatcher', () => { } ); it( 'should be possible to override', () => { - range = ModelRange.createIn( root ); + range = model.createRangeIn( root ); const addMarkerSpy = sinon.spy(); const highAddMarkerSpy = sinon.spy(); @@ -528,7 +533,7 @@ describe( 'DowncastDispatcher', () => { element = new ModelElement( 'paragraph', null, [ text ] ); root._appendChild( [ element ] ); - range = ModelRange.createFromParentsAndOffsets( element, 0, element, 4 ); + range = model.createRange( model.createPositionAt( element, 0 ), model.createPositionAt( element, 4 ) ); } ); it( 'should fire removeMarker event', () => { @@ -540,7 +545,7 @@ describe( 'DowncastDispatcher', () => { } ); it( 'should not convert marker if it is in graveyard', () => { - const gyRange = ModelRange.createFromParentsAndOffsets( doc.graveyard, 0, doc.graveyard, 0 ); + const gyRange = model.createRange( model.createPositionAt( doc.graveyard, 0 ), model.createPositionAt( doc.graveyard, 0 ) ); sinon.spy( dispatcher, 'fire' ); dispatcher.convertMarkerRemove( 'name', gyRange ); @@ -550,7 +555,7 @@ describe( 'DowncastDispatcher', () => { it( 'should not convert marker if it is not in model root', () => { const element = new ModelElement( 'element', null, new ModelText( 'foo' ) ); - const eleRange = ModelRange.createFromParentsAndOffsets( element, 1, element, 2 ); + const eleRange = model.createRange( model.createPositionAt( element, 1 ), model.createPositionAt( element, 2 ) ); sinon.spy( dispatcher, 'fire' ); dispatcher.convertMarkerRemove( 'name', eleRange ); @@ -559,7 +564,7 @@ describe( 'DowncastDispatcher', () => { } ); it( 'should fire conversion for the range', () => { - range = ModelRange.createIn( root ); + range = model.createRangeIn( root ); dispatcher.on( 'addMarker:name', ( evt, data ) => { expect( data.markerName ).to.equal( 'name' ); @@ -570,7 +575,7 @@ describe( 'DowncastDispatcher', () => { } ); it( 'should be possible to override', () => { - range = ModelRange.createIn( root ); + range = model.createRangeIn( root ); const removeMarkerSpy = sinon.spy(); const highRemoveMarkerSpy = sinon.spy(); diff --git a/tests/conversion/mapper.js b/tests/conversion/mapper.js index b14526d63..da70aca6f 100644 --- a/tests/conversion/mapper.js +++ b/tests/conversion/mapper.js @@ -379,7 +379,7 @@ describe( 'Mapper', () => { describe( 'toModelRange', () => { it( 'should transform range', () => { - const viewRange = ViewRange.createFromParentsAndOffsets( viewDiv, 0, viewTextFOO, 2 ); + const viewRange = ViewRange._createFromParentsAndOffsets( viewDiv, 0, viewTextFOO, 2 ); const modelRange = mapper.toModelRange( viewRange ); expect( modelRange.start.parent ).to.equal( modelDiv ); expect( modelRange.start.offset ).to.equal( 0 ); @@ -390,7 +390,7 @@ describe( 'Mapper', () => { describe( 'toViewRange', () => { it( 'should transform range', () => { - const modelRange = ModelRange.createFromParentsAndOffsets( modelDiv, 0, modelP, 3 ); + const modelRange = new ModelRange( ModelPosition._createAt( modelDiv, 0 ), ModelPosition._createAt( modelP, 3 ) ); const viewRange = mapper.toViewRange( modelRange ); expect( viewRange.start.parent ).to.equal( viewTextX ); expect( viewRange.start.offset ).to.equal( 0 ); @@ -400,7 +400,7 @@ describe( 'Mapper', () => { } ); function createToViewTest( modelElement, modelOffset, viewElement, viewOffset ) { - const modelPosition = ModelPosition.createFromParentAndOffset( modelElement, modelOffset ); + const modelPosition = ModelPosition._createAt( modelElement, modelOffset ); const viewPosition = mapper.toViewPosition( modelPosition ); expect( viewPosition.parent ).to.equal( viewElement ); expect( viewPosition.offset ).to.equal( viewOffset ); @@ -530,7 +530,7 @@ describe( 'Mapper', () => { } ); function createToViewTest( modelElement, modelOffset, viewElement, viewOffset ) { - const modelPosition = ModelPosition.createFromParentAndOffset( modelElement, modelOffset ); + const modelPosition = ModelPosition._createAt( modelElement, modelOffset ); const viewPosition = mapper.toViewPosition( modelPosition ); expect( viewPosition.parent ).to.equal( viewElement ); expect( viewPosition.offset ).to.equal( viewOffset ); diff --git a/tests/conversion/upcast-converters.js b/tests/conversion/upcast-converters.js index 44ed080f3..32fdb4a7b 100644 --- a/tests/conversion/upcast-converters.js +++ b/tests/conversion/upcast-converters.js @@ -761,7 +761,7 @@ describe( 'upcast-converters', () => { if ( conversionApi.consumable.consume( data.viewItem ) ) { const text = conversionApi.writer.createText( data.viewItem.data.replace( /fuck/gi, '****' ) ); conversionApi.writer.insert( text, data.modelCursor ); - data.modelRange = ModelRange.createFromPositionAndShift( data.modelCursor, text.offsetSize ); + data.modelRange = ModelRange._createFromPositionAndShift( data.modelCursor, text.offsetSize ); data.modelCursor = data.modelRange.end; } } ); @@ -841,9 +841,9 @@ describe( 'upcast-converters', () => { const paragraph = conversionApi.writer.createElement( 'paragraph' ); conversionApi.writer.insert( paragraph, data.modelCursor ); - conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( paragraph, 0 ) ); + conversionApi.convertChildren( data.viewItem, ModelPosition._createAt( paragraph, 0 ) ); - data.modelRange = ModelRange.createOn( paragraph ); + data.modelRange = ModelRange._createOn( paragraph ); data.modelCursor = data.modelRange.end; } } ); @@ -863,7 +863,7 @@ describe( 'upcast-converters', () => { new ViewContainerElement( 'div', null, [ new ViewText( 'abc' ), new ViewContainerElement( 'foo' ) ] ), new ViewContainerElement( 'bar' ) ] ); - const position = ModelPosition.createAt( new ModelElement( 'element' ), 0 ); + const position = ModelPosition._createAt( new ModelElement( 'element' ), 0 ); dispatcher.on( 'documentFragment', convertToModelFragment() ); dispatcher.on( 'element', convertToModelFragment(), { priority: 'lowest' } ); diff --git a/tests/conversion/upcast-selection-converters.js b/tests/conversion/upcast-selection-converters.js index c62b1fc3b..18a95d92f 100644 --- a/tests/conversion/upcast-selection-converters.js +++ b/tests/conversion/upcast-selection-converters.js @@ -46,7 +46,7 @@ describe( 'convertSelectionChange', () => { it( 'should convert collapsed selection', () => { const viewSelection = new ViewSelection(); - viewSelection.setTo( ViewRange.createFromParentsAndOffsets( + viewSelection.setTo( ViewRange._createFromParentsAndOffsets( viewRoot.getChild( 0 ).getChild( 0 ), 1, viewRoot.getChild( 0 ).getChild( 0 ), 1 ) ); convertSelection( null, { newSelection: viewSelection } ); @@ -63,7 +63,7 @@ describe( 'convertSelectionChange', () => { mapper.bindElements( modelRoot.getChild( 0 ), viewRoot.getChild( 0 ) ); const viewSelection = new ViewSelection( [ - ViewRange.createFromParentsAndOffsets( viewRoot.getChild( 0 ).getChild( 0 ), 2, viewRoot.getChild( 0 ).getChild( 0 ), 6 ) + ViewRange._createFromParentsAndOffsets( viewRoot.getChild( 0 ).getChild( 0 ), 2, viewRoot.getChild( 0 ).getChild( 0 ), 6 ) ] ); convertSelection( null, { newSelection: viewSelection } ); @@ -73,9 +73,9 @@ describe( 'convertSelectionChange', () => { it( 'should convert multi ranges selection', () => { const viewSelection = new ViewSelection( [ - ViewRange.createFromParentsAndOffsets( + ViewRange._createFromParentsAndOffsets( viewRoot.getChild( 0 ).getChild( 0 ), 1, viewRoot.getChild( 0 ).getChild( 0 ), 2 ), - ViewRange.createFromParentsAndOffsets( + ViewRange._createFromParentsAndOffsets( viewRoot.getChild( 1 ).getChild( 0 ), 1, viewRoot.getChild( 1 ).getChild( 0 ), 2 ) ] ); @@ -100,9 +100,9 @@ describe( 'convertSelectionChange', () => { it( 'should convert reverse selection', () => { const viewSelection = new ViewSelection( [ - ViewRange.createFromParentsAndOffsets( + ViewRange._createFromParentsAndOffsets( viewRoot.getChild( 0 ).getChild( 0 ), 1, viewRoot.getChild( 0 ).getChild( 0 ), 2 ), - ViewRange.createFromParentsAndOffsets( + ViewRange._createFromParentsAndOffsets( viewRoot.getChild( 1 ).getChild( 0 ), 1, viewRoot.getChild( 1 ).getChild( 0 ), 2 ) ], { backward: true } ); @@ -114,7 +114,7 @@ describe( 'convertSelectionChange', () => { it( 'should not enqueue changes if selection has not changed', () => { const viewSelection = new ViewSelection( [ - ViewRange.createFromParentsAndOffsets( + ViewRange._createFromParentsAndOffsets( viewRoot.getChild( 0 ).getChild( 0 ), 1, viewRoot.getChild( 0 ).getChild( 0 ), 1 ) ] ); diff --git a/tests/conversion/upcastdispatcher.js b/tests/conversion/upcastdispatcher.js index da6e162c3..4b6aca334 100644 --- a/tests/conversion/upcastdispatcher.js +++ b/tests/conversion/upcastdispatcher.js @@ -162,7 +162,7 @@ describe( 'UpcastDispatcher', () => { // Set conversion result to `modelRange` property of `data`. // Later we will check if it was returned by `convert` method. - data.modelRange = ModelRange.createOn( text ); + data.modelRange = ModelRange._createOn( text ); } ); const conversionResult = model.change( writer => dispatcher.convert( viewText, writer ) ); @@ -199,7 +199,7 @@ describe( 'UpcastDispatcher', () => { // Set conversion result to `modelRange` property of `data`. // Later we will check if it was returned by `convert` method. - data.modelRange = ModelRange.createOn( paragraph ); + data.modelRange = ModelRange._createOn( paragraph ); } ); // Use `additionalData` parameter to check if it was passed to the event. @@ -236,7 +236,7 @@ describe( 'UpcastDispatcher', () => { // Set conversion result to `modelRange` property of `data`. // Later we will check if it was returned by `convert` method. - data.modelRange = ModelRange.createOn( text ); + data.modelRange = ModelRange._createOn( text ); } ); const conversionResult = model.change( writer => dispatcher.convert( viewFragment, writer ) ); @@ -262,25 +262,25 @@ describe( 'UpcastDispatcher', () => { // Create and insert empty split element before target element. const emptySplit = conversionApi.writer.createElement( 'paragraph' ); - conversionApi.writer.insert( emptySplit, ModelPosition.createAfter( paragraph ) ); + conversionApi.writer.insert( emptySplit, ModelPosition._createAfter( paragraph ) ); // Create and insert not empty split after target element. const notEmptySplit = conversionApi.writer.createElement( 'paragraph' ); conversionApi.writer.appendText( 'foo', notEmptySplit ); - conversionApi.writer.insert( notEmptySplit, ModelPosition.createAfter( emptySplit ) ); + conversionApi.writer.insert( notEmptySplit, ModelPosition._createAfter( emptySplit ) ); // Create and insert split with other split inside (both should be removed) const outerSplit = conversionApi.writer.createElement( 'paragraph' ); const innerSplit = conversionApi.writer.createElement( 'paragraph' ); conversionApi.writer.append( innerSplit, outerSplit ); - conversionApi.writer.insert( outerSplit, ModelPosition.createBefore( paragraph ) ); + conversionApi.writer.insert( outerSplit, ModelPosition._createBefore( paragraph ) ); dispatcher._removeIfEmpty.add( emptySplit ); dispatcher._removeIfEmpty.add( notEmptySplit ); dispatcher._removeIfEmpty.add( outerSplit ); dispatcher._removeIfEmpty.add( innerSplit ); - data.modelRange = ModelRange.createOn( paragraph ); + data.modelRange = ModelRange._createOn( paragraph ); data.modelCursor = data.modelRange.end; // We have the following result: @@ -321,7 +321,7 @@ describe( 'UpcastDispatcher', () => { conversionApi.writer.insert( fragment, data.modelCursor ); // Create range on this fragment as a conversion result. - data.modelRange = ModelRange.createIn( data.modelCursor.parent ); + data.modelRange = ModelRange._createIn( data.modelCursor.parent ); } ); const conversionResult = model.change( writer => dispatcher.convert( viewFragment, writer ) ); @@ -404,14 +404,14 @@ describe( 'UpcastDispatcher', () => { dispatcher.on( 'element:p', ( evt, data ) => { spyP(); - data.modelRange = ModelRange.createOn( modelP ); + data.modelRange = ModelRange._createOn( modelP ); data.modelCursor = data.modelRange.end; } ); dispatcher.on( 'text', ( evt, data ) => { spyText(); - data.modelRange = ModelRange.createOn( modelText ); + data.modelRange = ModelRange._createOn( modelText ); data.modelCursor = data.modelRange.end; } ); @@ -501,7 +501,7 @@ describe( 'UpcastDispatcher', () => { dispatcher.on( 'documentFragment', ( evt, data, conversionApi ) => { spy(); - const result = conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( rootMock, 0 ) ); + const result = conversionApi.convertChildren( data.viewItem, ModelPosition._createAt( rootMock, 0 ) ); expect( result.modelRange ).to.be.instanceof( ModelRange ); expect( result.modelRange.start.path ).to.deep.equal( [ 0 ] ); @@ -540,7 +540,7 @@ describe( 'UpcastDispatcher', () => { dispatcher.on( 'documentFragment', ( evt, data, conversionApi ) => { const paragraph = conversionApi.writer.createElement( 'paragraph' ); const span = conversionApi.writer.createElement( 'span' ); - const position = ModelPosition.createAt( paragraph, 0 ); + const position = ModelPosition._createAt( paragraph, 0 ); const result = conversionApi.splitToAllowedParent( span, position ); @@ -572,13 +572,13 @@ describe( 'UpcastDispatcher', () => { conversionApi.writer.insert( paragraph, section ); conversionApi.writer.insert( span, paragraph ); - const position = ModelPosition.createAt( span, 0 ); + const position = ModelPosition._createAt( span, 0 ); const paragraph2 = conversionApi.writer.createElement( 'paragraph' ); const result = conversionApi.splitToAllowedParent( paragraph2, position ); expect( result ).to.deep.equal( { - position: ModelPosition.createAfter( paragraph ), + position: ModelPosition._createAfter( paragraph ), cursorParent: paragraph.parent.getChild( 1 ).getChild( 0 ) } ); @@ -597,7 +597,7 @@ describe( 'UpcastDispatcher', () => { dispatcher.on( 'documentFragment', ( evt, data, conversionApi ) => { const paragraph = conversionApi.writer.createElement( 'paragraph' ); const span = conversionApi.writer.createElement( 'span' ); - const position = ModelPosition.createAt( paragraph, 0 ); + const position = ModelPosition._createAt( paragraph, 0 ); const result = conversionApi.splitToAllowedParent( span, position ); diff --git a/tests/dev-utils/enableenginedebug.js b/tests/dev-utils/enableenginedebug.js index a4b45144f..ef3b1ce4f 100644 --- a/tests/dev-utils/enableenginedebug.js +++ b/tests/dev-utils/enableenginedebug.js @@ -183,9 +183,9 @@ describe( 'debug tools', () => { } ); it( 'for ModelRange', () => { - const rangeInRoot = ModelRange.createIn( modelRoot ); - const rangeInElement = ModelRange.createIn( modelElement ); - const rangeInDocFrag = ModelRange.createIn( modelDocFrag ); + const rangeInRoot = ModelRange._createIn( modelRoot ); + const rangeInElement = ModelRange._createIn( modelElement ); + const rangeInDocFrag = ModelRange._createIn( modelDocFrag ); expect( rangeInRoot.toString() ).to.equal( 'main [ 0 ] - [ 0 ]' ); expect( rangeInElement.toString() ).to.equal( ' [ 0 ] - [ 3 ]' ); @@ -226,7 +226,7 @@ describe( 'debug tools', () => { } ); it( 'AttributeOperation', () => { - const op = new AttributeOperation( ModelRange.createIn( modelRoot ), 'key', null, { foo: 'bar' }, 0 ); + const op = new AttributeOperation( ModelRange._createIn( modelRoot ), 'key', null, { foo: 'bar' }, 0 ); expect( op.toString() ).to.equal( 'AttributeOperation( 0 ): "key": null -> {"foo":"bar"}, main [ 0 ] - [ 6 ]' ); @@ -235,7 +235,7 @@ describe( 'debug tools', () => { } ); it( 'DetachOperation (text node)', () => { - const op = new DetachOperation( ModelPosition.createAt( modelRoot, 0 ), 3 ); + const op = new DetachOperation( ModelPosition._createAt( modelRoot, 0 ), 3 ); expect( op.toString() ).to.equal( 'DetachOperation( null ): #foo -> main [ 0 ] - [ 3 ]' ); @@ -247,7 +247,7 @@ describe( 'debug tools', () => { const element = new ModelElement( 'element' ); modelRoot._insertChild( 0, element ); - const op = new DetachOperation( ModelPosition.createBefore( element ), 1 ); + const op = new DetachOperation( ModelPosition._createBefore( element ), 1 ); expect( op.toString() ).to.equal( 'DetachOperation( null ): -> main [ 0 ] - [ 1 ]' ); @@ -259,7 +259,7 @@ describe( 'debug tools', () => { const element = new ModelElement( 'element' ); modelRoot._insertChild( 0, element ); - const op = new DetachOperation( ModelPosition.createBefore( element ), 2 ); + const op = new DetachOperation( ModelPosition._createBefore( element ), 2 ); expect( op.toString() ).to.equal( 'DetachOperation( null ): [ 2 ] -> main [ 0 ] - [ 2 ]' ); @@ -268,7 +268,7 @@ describe( 'debug tools', () => { } ); it( 'InsertOperation (text node)', () => { - const op = new InsertOperation( ModelPosition.createAt( modelRoot, 3 ), [ new ModelText( 'abc' ) ], 0 ); + const op = new InsertOperation( ModelPosition._createAt( modelRoot, 3 ), [ new ModelText( 'abc' ) ], 0 ); expect( op.toString() ).to.equal( 'InsertOperation( 0 ): #abc -> main [ 3 ]' ); @@ -277,7 +277,7 @@ describe( 'debug tools', () => { } ); it( 'InsertOperation (element)', () => { - const op = new InsertOperation( ModelPosition.createAt( modelRoot, 3 ), [ new ModelElement( 'paragraph' ) ], 0 ); + const op = new InsertOperation( ModelPosition._createAt( modelRoot, 3 ), [ new ModelElement( 'paragraph' ) ], 0 ); expect( op.toString() ).to.equal( 'InsertOperation( 0 ): -> main [ 3 ]' ); @@ -287,7 +287,7 @@ describe( 'debug tools', () => { it( 'InsertOperation (multiple nodes)', () => { const nodes = [ new ModelText( 'x' ), new ModelElement( 'y' ), new ModelText( 'z' ) ]; - const op = new InsertOperation( ModelPosition.createAt( modelRoot, 3 ), nodes, 0 ); + const op = new InsertOperation( ModelPosition._createAt( modelRoot, 3 ), nodes, 0 ); expect( op.toString() ).to.equal( 'InsertOperation( 0 ): [ 3 ] -> main [ 3 ]' ); @@ -296,7 +296,7 @@ describe( 'debug tools', () => { } ); it( 'MarkerOperation', () => { - const op = new MarkerOperation( 'marker', null, ModelRange.createIn( modelRoot ), modelDoc.markers, false, 0 ); + const op = new MarkerOperation( 'marker', null, ModelRange._createIn( modelRoot ), modelDoc.markers, false, 0 ); expect( op.toString() ).to.equal( 'MarkerOperation( 0 ): "marker": null -> main [ 0 ] - [ 6 ]' ); @@ -305,7 +305,7 @@ describe( 'debug tools', () => { } ); it( 'MoveOperation', () => { - const op = new MoveOperation( ModelPosition.createAt( modelRoot, 1 ), 2, ModelPosition.createAt( modelRoot, 6 ), 0 ); + const op = new MoveOperation( ModelPosition._createAt( modelRoot, 1 ), 2, ModelPosition._createAt( modelRoot, 6 ), 0 ); expect( op.toString() ).to.equal( 'MoveOperation( 0 ): main [ 1 ] - [ 3 ] -> main [ 6 ]' ); @@ -323,7 +323,7 @@ describe( 'debug tools', () => { } ); it( 'RenameOperation', () => { - const op = new RenameOperation( ModelPosition.createAt( modelRoot, 1 ), 'old', 'new', 0 ); + const op = new RenameOperation( ModelPosition._createAt( modelRoot, 1 ), 'old', 'new', 0 ); expect( op.toString() ).to.equal( 'RenameOperation( 0 ): main [ 1 ]: "old" -> "new"' ); @@ -383,7 +383,7 @@ describe( 'debug tools', () => { } ); it( 'for applied operations', () => { - const op = new InsertOperation( ModelPosition.createAt( modelRoot, 0 ), [ new ModelText( 'foo' ) ], 0 ); + const op = new InsertOperation( ModelPosition._createAt( modelRoot, 0 ), [ new ModelText( 'foo' ) ], 0 ); model.applyOperation( op ); @@ -559,11 +559,11 @@ describe( 'debug tools', () => { const viewDoc = view.document; model.change( () => { - const insert = new InsertOperation( ModelPosition.createAt( modelRoot, 0 ), new ModelText( 'foobar' ), 0 ); + const insert = new InsertOperation( ModelPosition._createAt( modelRoot, 0 ), new ModelText( 'foobar' ), 0 ); model.applyOperation( insert ); const graveyard = modelDoc.graveyard; - const move = new MoveOperation( ModelPosition.createAt( modelRoot, 1 ), 2, ModelPosition.createAt( graveyard, 0 ), 1 ); + const move = new MoveOperation( ModelPosition._createAt( modelRoot, 1 ), 2, ModelPosition._createAt( graveyard, 0 ), 1 ); model.applyOperation( move ); } ); @@ -651,7 +651,7 @@ describe( 'debug tools', () => { const modelRoot = model.document.getRoot(); for ( let i = 0; i < 25; i++ ) { - const insert = new InsertOperation( ModelPosition.createAt( modelRoot, 0 ), new ModelText( 'foobar' ), modelDoc.version ); + const insert = new InsertOperation( ModelPosition._createAt( modelRoot, 0 ), new ModelText( 'foobar' ), modelDoc.version ); model.applyOperation( insert ); } @@ -672,7 +672,7 @@ describe( 'debug tools', () => { otherRoot._appendChild( element ); - const insert = new InsertOperation( ModelPosition.createAt( element, 0 ), new ModelText( 'foo' ), 0 ); + const insert = new InsertOperation( ModelPosition._createAt( element, 0 ), new ModelText( 'foo' ), 0 ); model.applyOperation( insert ); const stringifiedOperations = model.getAppliedOperations(); @@ -689,7 +689,7 @@ describe( 'debug tools', () => { otherRoot._appendChild( element ); - const insert = new InsertOperation( ModelPosition.createAt( element, 0 ), new ModelText( 'foo' ), 0 ); + const insert = new InsertOperation( ModelPosition._createAt( element, 0 ), new ModelText( 'foo' ), 0 ); model.applyOperation( insert ); const stringifiedOperations = model.getAppliedOperations(); diff --git a/tests/dev-utils/model.js b/tests/dev-utils/model.js index dcdae585a..b99b0f307 100644 --- a/tests/dev-utils/model.js +++ b/tests/dev-utils/model.js @@ -67,7 +67,7 @@ describe( 'model test utils', () => { const stringifySpy = sinon.spy( getData, '_stringify' ); root._appendChild( new Element( 'b', null, new Text( 'btext' ) ) ); model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( root, 0, root, 1 ) ); + writer.setSelection( new Range( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ) ); } ); expect( getData( model ) ).to.equal( '[btext]' ); sinon.assert.calledOnce( stringifySpy ); @@ -355,7 +355,7 @@ describe( 'model test utils', () => { it( 'writes flat selection containing couple of nodes', () => { model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( root, 0, root, 4 ) ); + writer.setSelection( new Range( Position._createAt( root, 0 ), Position._createAt( root, 4 ) ) ); } ); expect( stringify( root, selection ) ).to.equal( @@ -365,7 +365,7 @@ describe( 'model test utils', () => { it( 'writes flat selection within text', () => { model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( root, 2, root, 3 ) ); + writer.setSelection( new Range( Position._createAt( root, 2 ), Position._createAt( root, 3 ) ) ); } ); expect( stringify( root, selection ) ).to.equal( @@ -375,7 +375,7 @@ describe( 'model test utils', () => { it( 'writes multi-level selection', () => { model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( elA, 0, elB, 0 ) ); + writer.setSelection( new Range( Position._createAt( elA, 0 ), Position._createAt( elB, 0 ) ) ); } ); expect( stringify( root, selection ) ).to.equal( @@ -385,7 +385,7 @@ describe( 'model test utils', () => { it( 'writes selection when is backward', () => { model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( elA, 0, elB, 0 ), { backward: true } ); + writer.setSelection( new Range( Position._createAt( elA, 0 ), Position._createAt( elB, 0 ) ), { backward: true } ); } ); expect( stringify( root, selection ) ).to.equal( @@ -398,14 +398,14 @@ describe( 'model test utils', () => { root._appendChild( new Text( 'நிலைக்கு' ) ); model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( root, 2, root, 6 ) ); + writer.setSelection( new Range( Position._createAt( root, 2 ), Position._createAt( root, 6 ) ) ); } ); expect( stringify( root, selection ) ).to.equal( 'நி[லைக்]கு' ); } ); it( 'uses range and coverts it to selection', () => { - const range = Range.createFromParentsAndOffsets( elA, 0, elB, 0 ); + const range = new Range( Position._createAt( elA, 0 ), Position._createAt( elB, 0 ) ); expect( stringify( root, range ) ).to.equal( '[foo<$text bold="true">bar]' @@ -441,7 +441,9 @@ describe( 'model test utils', () => { expect( el ).to.be.instanceOf( Element ); expect( fragment ).to.be.instanceOf( DocumentFragment ); expect( selection.rangeCount ).to.equal( 1 ); - expect( selection.getFirstRange().isEqual( Range.createFromParentsAndOffsets( fragment, 0, fragment, 1 ) ) ).to.be.true; + + const range = new Range( Position._createAt( fragment, 0 ), Position._createAt( fragment, 1 ) ); + expect( selection.getFirstRange().isEqual( range ) ).to.be.true; } } ); diff --git a/tests/dev-utils/view.js b/tests/dev-utils/view.js index 3070858cc..754ef4f1a 100644 --- a/tests/dev-utils/view.js +++ b/tests/dev-utils/view.js @@ -64,7 +64,7 @@ describe( 'view test utils', () => { root._appendChild( new Element( 'p' ) ); view.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( root, 0, root, 1 ) ); + writer.setSelection( Range._createFromParentsAndOffsets( root, 0, root, 1 ) ); } ); expect( getData( view, options ) ).to.equal( '[

]' ); @@ -166,7 +166,7 @@ describe( 'view test utils', () => { const b1 = new Element( 'b', null, text1 ); const b2 = new Element( 'b', null, text2 ); const p = new Element( 'p', null, [ b1, b2 ] ); - const range = Range.createFromParentsAndOffsets( p, 1, p, 2 ); + const range = Range._createFromParentsAndOffsets( p, 1, p, 2 ); const selection = new DocumentSelection( [ range ] ); expect( stringify( p, selection ) ).to.equal( '

foobar[bazqux]

' ); } ); @@ -175,7 +175,7 @@ describe( 'view test utils', () => { const text = new Text( 'நிலைக்கு' ); const b = new Element( 'b', null, text ); const p = new Element( 'p', null, b ); - const range = Range.createFromParentsAndOffsets( p, 0, text, 4 ); + const range = Range._createFromParentsAndOffsets( p, 0, text, 4 ); const selection = new DocumentSelection( [ range ] ); expect( stringify( p, selection ) ).to.equal( '

[நிலை}க்கு

' ); @@ -184,7 +184,7 @@ describe( 'view test utils', () => { it( 'should write collapsed selection ranges inside elements', () => { const text = new Text( 'foobar' ); const p = new Element( 'p', null, text ); - const range = Range.createFromParentsAndOffsets( p, 0, p, 0 ); + const range = Range._createFromParentsAndOffsets( p, 0, p, 0 ); const selection = new DocumentSelection( [ range ] ); expect( stringify( p, selection ) ).to.equal( '

[]foobar

' ); } ); @@ -195,7 +195,7 @@ describe( 'view test utils', () => { const b1 = new Element( 'b', null, text1 ); const b2 = new Element( 'b', null, text2 ); const p = new Element( 'p', null, [ b1, b2 ] ); - const range = Range.createFromParentsAndOffsets( text1, 1, text1, 5 ); + const range = Range._createFromParentsAndOffsets( text1, 1, text1, 5 ); const selection = new DocumentSelection( [ range ] ); expect( stringify( p, selection ) ).to.equal( '

f{ooba}rbazqux

' ); } ); @@ -206,7 +206,7 @@ describe( 'view test utils', () => { const b1 = new Element( 'b', null, text1 ); const b2 = new Element( 'b', null, text2 ); const p = new Element( 'p', null, [ b1, b2 ] ); - const range = Range.createFromParentsAndOffsets( text1, 1, text1, 5 ); + const range = Range._createFromParentsAndOffsets( text1, 1, text1, 5 ); const selection = new DocumentSelection( [ range ] ); expect( stringify( p, selection, { sameSelectionCharacters: true } ) ) .to.equal( '

f[ooba]rbazqux

' ); @@ -215,7 +215,7 @@ describe( 'view test utils', () => { it( 'should write collapsed selection ranges inside texts', () => { const text = new Text( 'foobar' ); const p = new Element( 'p', null, text ); - const range = Range.createFromParentsAndOffsets( text, 0, text, 0 ); + const range = Range._createFromParentsAndOffsets( text, 0, text, 0 ); const selection = new DocumentSelection( [ range ] ); expect( stringify( p, selection ) ).to.equal( '

{}foobar

' ); } ); @@ -226,7 +226,7 @@ describe( 'view test utils', () => { const b1 = new Element( 'b', null, text1 ); const b2 = new Element( 'b', null, text2 ); const p = new Element( 'p', null, [ b1, b2 ] ); - const range = Range.createFromParentsAndOffsets( p, 0, text2, 5 ); + const range = Range._createFromParentsAndOffsets( p, 0, text2, 5 ); const selection = new DocumentSelection( [ range ] ); expect( stringify( p, selection ) ).to.equal( '

[foobarbazqu}x

' ); } ); @@ -277,7 +277,7 @@ describe( 'view test utils', () => { const text = new Text( 'foobar' ); const b = new Element( 'b', null, text ); const p = new Element( 'p', null, b ); - const range = Range.createFromParentsAndOffsets( p, 0, p, 5 ); + const range = Range._createFromParentsAndOffsets( p, 0, p, 5 ); expect( stringify( p, range ) ).to.equal( '

[foobar

' ); } ); @@ -286,7 +286,7 @@ describe( 'view test utils', () => { const text = new Text( 'foobar' ); const b = new Element( 'b', null, text ); const p = new Element( 'p', null, b ); - const range = Range.createFromParentsAndOffsets( p, -1, p, 1 ); + const range = Range._createFromParentsAndOffsets( p, -1, p, 1 ); expect( stringify( p, range ) ).to.equal( '

foobar]

' ); } ); @@ -295,7 +295,7 @@ describe( 'view test utils', () => { const text = new Text( 'foobar' ); const b = new Element( 'b', null, text ); const p = new Element( 'p', null, b ); - const range = Range.createFromParentsAndOffsets( text, 0, text, 7 ); + const range = Range._createFromParentsAndOffsets( text, 0, text, 7 ); expect( stringify( p, range ) ).to.equal( '

{foobar

' ); } ); @@ -304,7 +304,7 @@ describe( 'view test utils', () => { const text = new Text( 'foobar' ); const b = new Element( 'b', null, text ); const p = new Element( 'p', null, b ); - const range = Range.createFromParentsAndOffsets( text, -1, text, 2 ); + const range = Range._createFromParentsAndOffsets( text, -1, text, 2 ); expect( stringify( p, range ) ).to.equal( '

fo}obar

' ); } ); @@ -315,8 +315,8 @@ describe( 'view test utils', () => { const b1 = new Element( 'b', null, text1 ); const b2 = new Element( 'b', null, text2 ); const p = new Element( 'p', null, [ b1, b2 ] ); - const range1 = Range.createFromParentsAndOffsets( p, 0, p, 1 ); - const range2 = Range.createFromParentsAndOffsets( p, 1, p, 1 ); + const range1 = Range._createFromParentsAndOffsets( p, 0, p, 1 ); + const range2 = Range._createFromParentsAndOffsets( p, 1, p, 1 ); const selection = new DocumentSelection( [ range2, range1 ] ); expect( stringify( p, selection ) ).to.equal( '

[foobar][]bazqux

' ); @@ -327,10 +327,10 @@ describe( 'view test utils', () => { const text2 = new Text( 'bazqux' ); const b = new Element( 'b', null, text1 ); const p = new Element( 'p', null, [ b, text2 ] ); - const range1 = Range.createFromParentsAndOffsets( p, 0, p, 1 ); - const range2 = Range.createFromParentsAndOffsets( text2, 0, text2, 3 ); - const range3 = Range.createFromParentsAndOffsets( text2, 3, text2, 4 ); - const range4 = Range.createFromParentsAndOffsets( p, 1, p, 1 ); + const range1 = Range._createFromParentsAndOffsets( p, 0, p, 1 ); + const range2 = Range._createFromParentsAndOffsets( text2, 0, text2, 3 ); + const range3 = Range._createFromParentsAndOffsets( text2, 3, text2, 4 ); + const range4 = Range._createFromParentsAndOffsets( p, 1, p, 1 ); const selection = new DocumentSelection( [ range1, range2, range3, range4 ] ); expect( stringify( p, selection ) ).to.equal( '

[foobar][]{baz}{q}ux

' ); @@ -345,7 +345,7 @@ describe( 'view test utils', () => { it( 'should use Range instance instead of Selection', () => { const text = new Text( 'foobar' ); - const range = Range.createFromParentsAndOffsets( text, 3, text, 4 ); + const range = Range._createFromParentsAndOffsets( text, 3, text, 4 ); const string = stringify( text, range ); expect( string ).to.equal( 'foo{b}ar' ); } ); @@ -428,7 +428,7 @@ describe( 'view test utils', () => { expect( view ).to.be.instanceOf( DocumentFragment ); expect( selection.rangeCount ).to.equal( 1 ); - expect( selection.getFirstRange().isEqual( Range.createFromParentsAndOffsets( view, 0, view, 0 ) ) ).to.be.true; + expect( selection.getFirstRange().isEqual( Range._createFromParentsAndOffsets( view, 0, view, 0 ) ) ).to.be.true; } ); it( 'should return Element if range is around single element', () => { @@ -438,7 +438,7 @@ describe( 'view test utils', () => { expect( view ).to.be.instanceOf( Element ); expect( parent ).to.be.instanceOf( DocumentFragment ); expect( selection.rangeCount ).to.equal( 1 ); - expect( selection.getFirstRange().isEqual( Range.createFromParentsAndOffsets( parent, 0, parent, 1 ) ) ).to.be.true; + expect( selection.getFirstRange().isEqual( Range._createFromParentsAndOffsets( parent, 0, parent, 1 ) ) ).to.be.true; } ); it( 'should create DocumentFragment when multiple elements on root', () => { @@ -538,8 +538,8 @@ describe( 'view test utils', () => { expect( selection.rangeCount ).to.equal( 2 ); const ranges = [ ...selection.getRanges() ]; - expect( ranges[ 0 ].isEqual( Range.createFromParentsAndOffsets( view, 1, view, 3 ) ) ).to.be.true; - expect( ranges[ 1 ].isEqual( Range.createFromParentsAndOffsets( view, 4, view, 4 ) ) ).to.be.true; + expect( ranges[ 0 ].isEqual( Range._createFromParentsAndOffsets( view, 1, view, 3 ) ) ).to.be.true; + expect( ranges[ 1 ].isEqual( Range._createFromParentsAndOffsets( view, 4, view, 4 ) ) ).to.be.true; } ); it( 'should parse selection range between elements', () => { @@ -555,8 +555,8 @@ describe( 'view test utils', () => { expect( text.data ).to.equal( 'foobar' ); expect( selection.rangeCount ).to.equal( 2 ); const ranges = [ ...selection.getRanges() ]; - expect( ranges[ 0 ].isEqual( Range.createFromParentsAndOffsets( view, 0, b, 1 ) ) ).to.be.true; - expect( ranges[ 1 ].isEqual( Range.createFromParentsAndOffsets( view, 1, view, 1 ) ) ).to.be.true; + expect( ranges[ 0 ].isEqual( Range._createFromParentsAndOffsets( view, 0, b, 1 ) ) ).to.be.true; + expect( ranges[ 1 ].isEqual( Range._createFromParentsAndOffsets( view, 1, view, 1 ) ) ).to.be.true; } ); it( 'should support unicode', () => { @@ -590,7 +590,7 @@ describe( 'view test utils', () => { expect( text ).to.be.instanceof( Text ); expect( text.data ).to.equal( 'foobar' ); expect( selection.rangeCount ).to.equal( 1 ); - expect( selection.getFirstRange().isEqual( Range.createFromParentsAndOffsets( text, 3, view, 1 ) ) ).to.be.true; + expect( selection.getFirstRange().isEqual( Range._createFromParentsAndOffsets( text, 3, view, 1 ) ) ).to.be.true; } ); it( 'should parse ranges #2', () => { @@ -608,17 +608,17 @@ describe( 'view test utils', () => { expect( text2.data ).to.equal( 'baz' ); expect( selection.rangeCount ).to.equal( 2 ); const ranges = [ ...selection.getRanges() ]; - expect( ranges[ 0 ].isEqual( Range.createFromParentsAndOffsets( view, 0, text1, 4 ) ) ).to.be.true; - expect( ranges[ 1 ].isEqual( Range.createFromParentsAndOffsets( text2, 0, view, 2 ) ) ).to.be.true; + expect( ranges[ 0 ].isEqual( Range._createFromParentsAndOffsets( view, 0, text1, 4 ) ) ).to.be.true; + expect( ranges[ 1 ].isEqual( Range._createFromParentsAndOffsets( text2, 0, view, 2 ) ) ).to.be.true; } ); it( 'should use ranges order when provided', () => { const { view, selection } = parse( '{f}oo{b}arb{a}z', { order: [ 3, 1, 2 ] } ); expect( selection.rangeCount ).to.equal( 3 ); const ranges = [ ...selection.getRanges() ]; - expect( ranges[ 0 ].isEqual( Range.createFromParentsAndOffsets( view, 3, view, 4 ) ) ).to.be.true; - expect( ranges[ 1 ].isEqual( Range.createFromParentsAndOffsets( view, 7, view, 8 ) ) ).to.be.true; - expect( ranges[ 2 ].isEqual( Range.createFromParentsAndOffsets( view, 0, view, 1 ) ) ).to.be.true; + expect( ranges[ 0 ].isEqual( Range._createFromParentsAndOffsets( view, 3, view, 4 ) ) ).to.be.true; + expect( ranges[ 1 ].isEqual( Range._createFromParentsAndOffsets( view, 7, view, 8 ) ) ).to.be.true; + expect( ranges[ 2 ].isEqual( Range._createFromParentsAndOffsets( view, 0, view, 1 ) ) ).to.be.true; expect( selection.anchor.isEqual( ranges[ 2 ].start ) ).to.be.true; expect( selection.focus.isEqual( ranges[ 2 ].end ) ).to.be.true; } ); @@ -627,9 +627,9 @@ describe( 'view test utils', () => { const { view, selection } = parse( '{f}oo{b}arb{a}z', { order: [ 3, 1, 2 ], lastRangeBackward: true } ); expect( selection.rangeCount ).to.equal( 3 ); const ranges = [ ...selection.getRanges() ]; - expect( ranges[ 0 ].isEqual( Range.createFromParentsAndOffsets( view, 3, view, 4 ) ) ).to.be.true; - expect( ranges[ 1 ].isEqual( Range.createFromParentsAndOffsets( view, 7, view, 8 ) ) ).to.be.true; - expect( ranges[ 2 ].isEqual( Range.createFromParentsAndOffsets( view, 0, view, 1 ) ) ).to.be.true; + expect( ranges[ 0 ].isEqual( Range._createFromParentsAndOffsets( view, 3, view, 4 ) ) ).to.be.true; + expect( ranges[ 1 ].isEqual( Range._createFromParentsAndOffsets( view, 7, view, 8 ) ) ).to.be.true; + expect( ranges[ 2 ].isEqual( Range._createFromParentsAndOffsets( view, 0, view, 1 ) ) ).to.be.true; expect( selection.anchor.isEqual( ranges[ 2 ].end ) ).to.be.true; expect( selection.focus.isEqual( ranges[ 2 ].start ) ).to.be.true; } ); diff --git a/tests/manual/highlight.js b/tests/manual/highlight.js index 28283dda4..9af5600e7 100644 --- a/tests/manual/highlight.js +++ b/tests/manual/highlight.js @@ -5,9 +5,6 @@ /* global console, window, document */ -import ModelRange from '../../src/model/range'; -import ViewPosition from '../../src/view/position'; - import { upcastElementToElement, } from '../../src/conversion/upcast-converters'; @@ -51,7 +48,7 @@ class FancyWidget extends Plugin { model: 'fancywidget', view: ( modelItem, viewWriter ) => { const widgetElement = viewWriter.createContainerElement( 'figure', { class: 'fancy-widget' } ); - viewWriter.insert( ViewPosition.createAt( widgetElement ), viewWriter.createText( 'widget' ) ); + viewWriter.insert( viewWriter.createPositionAt( widgetElement ), viewWriter.createText( 'widget' ) ); return toWidget( widgetElement, viewWriter ); } @@ -127,7 +124,7 @@ ClassicEditor.create( global.document.querySelector( '#editor' ), { function addMarker( editor, color ) { editor.model.change( writer => { - const range = ModelRange.createFromRange( editor.model.document.selection.getFirstRange() ); + const range = editor.model.document.selection.getFirstRange(); writer.addMarker( 'marker:' + color, { range, usingOperation: false } ); } ); } diff --git a/tests/manual/markers.js b/tests/manual/markers.js index 214b36136..c96bc9428 100644 --- a/tests/manual/markers.js +++ b/tests/manual/markers.js @@ -108,7 +108,7 @@ function uid() { function addHighlight( color ) { model.change( writer => { - const range = Range.createFromRange( model.document.selection.getFirstRange() ); + const range = model.document.selection.getFirstRange(); const name = 'highlight:' + color + ':' + uid(); markerNames.push( name ); diff --git a/tests/manual/tickets/475/1.js b/tests/manual/tickets/475/1.js index 7235c4192..ca8f71e5a 100644 --- a/tests/manual/tickets/475/1.js +++ b/tests/manual/tickets/475/1.js @@ -70,9 +70,9 @@ class AutoLinker extends Plugin { const length = url.length; if ( entry.position.offset + entry.length == index + length ) { - const livePos = LivePosition.createFromParentAndOffset( parent, index ); + const livePos = LivePosition._createAt( parent, index ); this.editor.model.enqueueChange( writer => { - const urlRange = Range.createFromPositionAndShift( livePos, length ); + const urlRange = Range._createFromPositionAndShift( livePos, length ); writer.setAttribute( 'link', url, urlRange ); } ); return; diff --git a/tests/manual/tickets/ckeditor5-721/1.js b/tests/manual/tickets/ckeditor5-721/1.js index c298f3178..e0b491e1b 100644 --- a/tests/manual/tickets/ckeditor5-721/1.js +++ b/tests/manual/tickets/ckeditor5-721/1.js @@ -47,7 +47,7 @@ ClassicEditor const b = writer.createAttributeElement( 'b' ); const div = writer.createContainerElement( 'div' ); - writer.insert( ViewPosition.createAt( div ), b ); + writer.insert( ViewPosition._createAt( div ), b ); return toWidget( div, writer, { label: 'element label' } ); } diff --git a/tests/model/_utils/utils.js b/tests/model/_utils/utils.js index b2f97571d..db24eb62d 100644 --- a/tests/model/_utils/utils.js +++ b/tests/model/_utils/utils.js @@ -4,6 +4,7 @@ */ import Range from '../../../src/model/range'; +import Position from '../../../src/model/position'; import TreeWalker from '../../../src/model/treewalker'; import Text from '../../../src/model/text'; import TextProxy from '../../../src/model/textproxy'; @@ -85,5 +86,5 @@ export function getText( element ) { * @returns {engine.model.Range} */ export function createRangeOnElementOnly( element ) { - return Range.createFromParentsAndOffsets( element.parent, element.startOffset, element, 0 ); + return new Range( Position._createAt( element.parent, element.startOffset ), Position._createAt( element, 0 ) ); } diff --git a/tests/model/differ.js b/tests/model/differ.js index f972bb058..fd1b09857 100644 --- a/tests/model/differ.js +++ b/tests/model/differ.js @@ -139,9 +139,9 @@ describe( 'Differ', () => { insert( image, position ); const caption = new Element( 'caption' ); - insert( caption, Position.createAt( image, 0 ) ); + insert( caption, Position._createAt( image, 0 ) ); - insert( new Text( 'foo' ), Position.createAt( caption, 0 ) ); + insert( new Text( 'foo' ), Position._createAt( caption, 0 ) ); expectChanges( [ { type: 'insert', name: 'image', length: 1, position } @@ -168,13 +168,13 @@ describe( 'Differ', () => { it( 'node in a element with changed attribute', () => { const text = new Text( 'xyz', { bold: true } ); const position = new Position( root, [ 0, 3 ] ); - const range = Range.createFromParentsAndOffsets( root, 0, root, 1 ); + const range = new Range( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ); model.change( () => { insert( text, position ); attribute( range, 'align', null, 'center' ); - const diffRange = Range.createFromParentsAndOffsets( root, 0, root.getChild( 0 ), 0 ); + const diffRange = new Range( Position._createAt( root, 0 ), Position._createAt( root.getChild( 0 ), 0 ) ); // Compare to scenario above, this time there is only an attribute change on parent element, // so there is also a diff for text. @@ -198,14 +198,14 @@ describe( 'Differ', () => { it( 'nodes before nodes with changed attributes', () => { const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 1, p1, 3 ); + const range = new Range( Position._createAt( p1, 1 ), Position._createAt( p1, 3 ) ); const position = new Position( root, [ 0, 0 ] ); model.change( () => { attribute( range, 'bold', null, true ); insert( new Text( 'xx' ), position ); - const rangeAfter = Range.createFromParentsAndOffsets( p1, 3, p1, 5 ); + const rangeAfter = new Range( Position._createAt( p1, 3 ), Position._createAt( p1, 5 ) ); expectChanges( [ { type: 'insert', name: '$text', length: 2, position }, @@ -216,15 +216,15 @@ describe( 'Differ', () => { it( 'nodes between nodes with changed attributes', () => { const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 1, p1, 3 ); + const range = new Range( Position._createAt( p1, 1 ), Position._createAt( p1, 3 ) ); const position = new Position( root, [ 0, 2 ] ); model.change( () => { attribute( range, 'bold', null, true ); insert( new Text( 'xx' ), position ); - const rangeBefore = Range.createFromParentsAndOffsets( p1, 1, p1, 2 ); - const rangeAfter = Range.createFromParentsAndOffsets( p1, 4, p1, 5 ); + const rangeBefore = new Range( Position._createAt( p1, 1 ), Position._createAt( p1, 2 ) ); + const rangeAfter = new Range( Position._createAt( p1, 4 ), Position._createAt( p1, 5 ) ); expectChanges( [ { @@ -248,7 +248,7 @@ describe( 'Differ', () => { it( 'nodes after nodes with changed attributes', () => { const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 1, p1, 3 ); + const range = new Range( Position._createAt( p1, 1 ), Position._createAt( p1, 3 ) ); const position = new Position( root, [ 0, 3 ] ); model.change( () => { @@ -440,13 +440,13 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 0 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 2, p1, 3 ); + const range = new Range( Position._createAt( p1, 2 ), Position._createAt( p1, 3 ) ); model.change( () => { attribute( range, 'bold', null, true ); remove( position, 1 ); - const newRange = Range.createFromParentsAndOffsets( p1, 1, p1, 2 ); + const newRange = new Range( Position._createAt( p1, 1 ), Position._createAt( p1, 2 ) ); expectChanges( [ { type: 'remove', name: '$text', length: 1, position }, @@ -465,13 +465,13 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 0 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 1, p1, 3 ); + const range = new Range( Position._createAt( p1, 1 ), Position._createAt( p1, 3 ) ); model.change( () => { attribute( range, 'bold', null, true ); remove( position, 2 ); - const newRange = Range.createFromParentsAndOffsets( p1, 0, p1, 1 ); + const newRange = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 1 ) ); expectChanges( [ { type: 'remove', name: '$text', length: 2, position }, @@ -490,14 +490,14 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 1 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 0, p1, 3 ); + const range = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 3 ) ); model.change( () => { attribute( range, 'bold', null, true ); remove( position, 1 ); - const rangeBefore = Range.createFromParentsAndOffsets( p1, 0, p1, 1 ); - const rangeAfter = Range.createFromParentsAndOffsets( p1, 1, p1, 2 ); + const rangeBefore = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 1 ) ); + const rangeAfter = new Range( Position._createAt( p1, 1 ), Position._createAt( p1, 2 ) ); expectChanges( [ { @@ -523,13 +523,13 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 1 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 0, p1, 2 ); + const range = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 2 ) ); model.change( () => { attribute( range, 'bold', null, true ); remove( position, 2 ); - const newRange = Range.createFromParentsAndOffsets( p1, 0, p1, 1 ); + const newRange = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 1 ) ); expectChanges( [ { @@ -548,7 +548,7 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 2 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 0, p1, 1 ); + const range = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 1 ) ); model.change( () => { attribute( range, 'bold', null, true ); @@ -698,12 +698,12 @@ describe( 'Differ', () => { const attributeNewValue = 'foo'; it( 'on an element', () => { - const range = Range.createFromParentsAndOffsets( root, 0, root, 1 ); + const range = new Range( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ); model.change( () => { attribute( range, attributeKey, attributeOldValue, attributeNewValue ); - const diffRange = Range.createFromParentsAndOffsets( root, 0, root.getChild( 0 ), 0 ); + const diffRange = new Range( Position._createAt( root, 0 ), Position._createAt( root.getChild( 0 ), 0 ) ); expectChanges( [ { type: 'attribute', range: diffRange, attributeKey, attributeOldValue, attributeNewValue } @@ -712,7 +712,7 @@ describe( 'Differ', () => { } ); it( 'on an element - only one of many attributes changes', () => { - const range = Range.createFromParentsAndOffsets( root, 0, root, 1 ); + const range = new Range( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ); model.change( () => { // Set an attribute on an element. It won't change afterwards. @@ -722,7 +722,7 @@ describe( 'Differ', () => { model.change( () => { attribute( range, attributeKey, attributeOldValue, attributeNewValue ); - const diffRange = Range.createFromParentsAndOffsets( root, 0, root.getChild( 0 ), 0 ); + const diffRange = new Range( Position._createAt( root, 0 ), Position._createAt( root.getChild( 0 ), 0 ) ); expectChanges( [ { type: 'attribute', range: diffRange, attributeKey, attributeOldValue, attributeNewValue } @@ -732,7 +732,7 @@ describe( 'Differ', () => { it( 'on a character', () => { const parent = root.getChild( 1 ); - const range = Range.createFromParentsAndOffsets( parent, 1, parent, 2 ); + const range = new Range( Position._createAt( parent, 1 ), Position._createAt( parent, 2 ) ); model.change( () => { attribute( range, attributeKey, attributeOldValue, attributeNewValue ); @@ -745,7 +745,7 @@ describe( 'Differ', () => { it( 'on a character - case with same characters next to each other', () => { const parent = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( parent, 1, parent, 2 ); + const range = new Range( Position._createAt( parent, 1 ), Position._createAt( parent, 2 ) ); model.change( () => { attribute( range, attributeKey, attributeOldValue, attributeNewValue ); @@ -758,7 +758,7 @@ describe( 'Differ', () => { it( 'on multiple characters', () => { const parent = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( parent, 0, parent, 3 ); + const range = new Range( Position._createAt( parent, 0 ), Position._createAt( parent, 3 ) ); model.change( () => { attribute( range, attributeKey, attributeOldValue, attributeNewValue ); @@ -772,14 +772,14 @@ describe( 'Differ', () => { it( 'on multiple consecutive characters in multiple operations', () => { const parent = root.getChild( 0 ); - const range1 = Range.createFromParentsAndOffsets( parent, 1, parent, 2 ); - const range2 = Range.createFromParentsAndOffsets( parent, 2, parent, 3 ); + const range1 = new Range( Position._createAt( parent, 1 ), Position._createAt( parent, 2 ) ); + const range2 = new Range( Position._createAt( parent, 2 ), Position._createAt( parent, 3 ) ); model.change( () => { attribute( range1, attributeKey, attributeOldValue, attributeNewValue ); attribute( range2, attributeKey, attributeOldValue, attributeNewValue ); - const range = Range.createFromParentsAndOffsets( parent, 1, parent, 3 ); + const range = new Range( Position._createAt( parent, 1 ), Position._createAt( parent, 3 ) ); expectChanges( [ { type: 'attribute', range, attributeKey, attributeOldValue, attributeNewValue } @@ -799,7 +799,7 @@ describe( 'Differ', () => { model.change( () => { for ( const item of ranges ) { - const range = Range.createFromParentsAndOffsets( parent, item[ 0 ], parent, item[ 1 ] ); + const range = new Range( Position._createAt( parent, item[ 0 ] ), Position._createAt( parent, item[ 1 ] ) ); attribute( range, item[ 4 ], item[ 2 ], item[ 3 ] ); } @@ -807,14 +807,14 @@ describe( 'Differ', () => { expectChanges( [ { type: 'attribute', - range: Range.createFromParentsAndOffsets( parent, 0, parent, 2 ), + range: new Range( Position._createAt( parent, 0 ), Position._createAt( parent, 2 ) ), attributeKey: 'foo', attributeOldValue: null, attributeNewValue: true }, { type: 'attribute', - range: Range.createFromParentsAndOffsets( parent, 1, parent, 3 ), + range: new Range( Position._createAt( parent, 1 ), Position._createAt( parent, 3 ) ), attributeKey: 'bar', attributeOldValue: null, attributeNewValue: true @@ -835,7 +835,7 @@ describe( 'Differ', () => { model.change( () => { for ( const item of ranges ) { - const range = Range.createFromParentsAndOffsets( parent, item[ 0 ], parent, item[ 1 ] ); + const range = new Range( Position._createAt( parent, item[ 0 ] ), Position._createAt( parent, item[ 1 ] ) ); attribute( range, item[ 4 ], item[ 2 ], item[ 3 ] ); } @@ -843,28 +843,28 @@ describe( 'Differ', () => { expectChanges( [ { type: 'attribute', - range: Range.createFromParentsAndOffsets( parent, 0, parent, 1 ), + range: new Range( Position._createAt( parent, 0 ), Position._createAt( parent, 1 ) ), attributeKey: 'bar', attributeOldValue: null, attributeNewValue: true }, { type: 'attribute', - range: Range.createFromParentsAndOffsets( parent, 1, parent, 2 ), + range: new Range( Position._createAt( parent, 1 ), Position._createAt( parent, 2 ) ), attributeKey: 'foo', attributeOldValue: null, attributeNewValue: true }, { type: 'attribute', - range: Range.createFromParentsAndOffsets( parent, 1, parent, 2 ), + range: new Range( Position._createAt( parent, 1 ), Position._createAt( parent, 2 ) ), attributeKey: 'bar', attributeOldValue: null, attributeNewValue: true }, { type: 'attribute', - range: Range.createFromParentsAndOffsets( parent, 2, parent, 3 ), + range: new Range( Position._createAt( parent, 2 ), Position._createAt( parent, 3 ) ), attributeKey: 'foo', attributeOldValue: null, attributeNewValue: true @@ -884,7 +884,7 @@ describe( 'Differ', () => { model.change( () => { for ( const item of ranges ) { - const range = Range.createFromParentsAndOffsets( parent, item[ 0 ], parent, item[ 1 ] ); + const range = new Range( Position._createAt( parent, item[ 0 ] ), Position._createAt( parent, item[ 1 ] ) ); attribute( range, attributeKey, item[ 2 ], item[ 3 ] ); } @@ -906,14 +906,14 @@ describe( 'Differ', () => { model.change( () => { for ( const item of ranges ) { - const range = Range.createFromParentsAndOffsets( parent, item[ 0 ], parent, item[ 1 ] ); + const range = new Range( Position._createAt( parent, item[ 0 ] ), Position._createAt( parent, item[ 1 ] ) ); attribute( range, attributeKey, item[ 2 ], item[ 3 ] ); } expectChanges( [ { type: 'attribute', - range: Range.createFromParentsAndOffsets( parent, 0, parent, 2 ), + range: new Range( Position._createAt( parent, 0 ), Position._createAt( parent, 2 ) ), attributeKey, attributeOldValue: null, attributeNewValue: true @@ -924,8 +924,8 @@ describe( 'Differ', () => { it( 'on multiple non-consecutive characters in multiple operations', () => { const parent = root.getChild( 0 ); - const range1 = Range.createFromParentsAndOffsets( parent, 0, parent, 1 ); - const range2 = Range.createFromParentsAndOffsets( parent, 2, parent, 3 ); + const range1 = new Range( Position._createAt( parent, 0 ), Position._createAt( parent, 1 ) ); + const range2 = new Range( Position._createAt( parent, 2 ), Position._createAt( parent, 3 ) ); model.change( () => { // Note "reversed" order of ranges. Further range is changed first. @@ -941,7 +941,7 @@ describe( 'Differ', () => { } ); it( 'on range containing various nodes', () => { - const range = Range.createFromParentsAndOffsets( root, 0, root, 2 ); + const range = new Range( Position._createAt( root, 0 ), Position._createAt( root, 2 ) ); model.change( () => { attribute( range, attributeKey, attributeOldValue, attributeNewValue ); @@ -953,14 +953,14 @@ describe( 'Differ', () => { expectChanges( [ { type, - range: Range.createFromParentsAndOffsets( root, 0, p1, 0 ), + range: new Range( Position._createAt( root, 0 ), Position._createAt( p1, 0 ) ), attributeKey, attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( root, 1, p2, 0 ), + range: new Range( Position._createAt( root, 1 ), Position._createAt( p2, 0 ) ), attributeKey, attributeOldValue, attributeNewValue @@ -974,14 +974,14 @@ describe( 'Differ', () => { p.getChild( 0 )._setAttribute( 'bold', true ); - const range = Range.createFromParentsAndOffsets( p, 1, p, 3 ); + const range = new Range( Position._createAt( p, 1 ), Position._createAt( p, 3 ) ); model.change( () => { attribute( range, 'bold', true, null ); attribute( range, 'italic', null, true ); - const range1 = Range.createFromParentsAndOffsets( p, 1, p, 2 ); - const range2 = Range.createFromParentsAndOffsets( p, 2, p, 3 ); + const range1 = new Range( Position._createAt( p, 1 ), Position._createAt( p, 2 ) ); + const range2 = new Range( Position._createAt( p, 2 ), Position._createAt( p, 3 ) ); // Attribute change glueing does not work 100% correct. expectChanges( [ @@ -1021,13 +1021,13 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 1 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 0, p1, 2 ); + const range = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 2 ) ); model.change( () => { insert( new Text( 'xx' ), position ); attribute( range, attributeKey, attributeOldValue, attributeNewValue ); - const rangeBefore = Range.createFromParentsAndOffsets( p1, 0, p1, 1 ); + const rangeBefore = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 1 ) ); expectChanges( [ { type: 'attribute', range: rangeBefore, attributeKey, attributeOldValue, attributeNewValue }, @@ -1040,7 +1040,7 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 1 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 2, p1, 3 ); + const range = new Range( Position._createAt( p1, 2 ), Position._createAt( p1, 3 ) ); model.change( () => { insert( new Text( 'xxx' ), position ); @@ -1056,13 +1056,13 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 1 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 2, p1, 4 ); + const range = new Range( Position._createAt( p1, 2 ), Position._createAt( p1, 4 ) ); model.change( () => { insert( new Text( 'xx' ), position ); attribute( range, attributeKey, attributeOldValue, attributeNewValue ); - const rangeAfter = Range.createFromParentsAndOffsets( p1, 3, p1, 4 ); + const rangeAfter = new Range( Position._createAt( p1, 3 ), Position._createAt( p1, 4 ) ); expectChanges( [ { type: 'insert', name: '$text', length: 2, position }, @@ -1075,14 +1075,14 @@ describe( 'Differ', () => { const position = new Position( root, [ 0, 1 ] ); const p1 = root.getChild( 0 ); - const range = Range.createFromParentsAndOffsets( p1, 0, p1, 4 ); + const range = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 4 ) ); model.change( () => { insert( new Text( 'xx' ), position ); attribute( range, attributeKey, attributeOldValue, attributeNewValue ); - const rangeBefore = Range.createFromParentsAndOffsets( p1, 0, p1, 1 ); - const rangeAfter = Range.createFromParentsAndOffsets( p1, 3, p1, 4 ); + const rangeBefore = new Range( Position._createAt( p1, 0 ), Position._createAt( p1, 1 ) ); + const rangeAfter = new Range( Position._createAt( p1, 3 ), Position._createAt( p1, 4 ) ); expectChanges( [ { type: 'attribute', range: rangeBefore, attributeKey, attributeOldValue, attributeNewValue }, @@ -1095,8 +1095,8 @@ describe( 'Differ', () => { it( 'on some not changed and some changed nodes', () => { const p = root.getChild( 0 ); - const rangeA = Range.createFromParentsAndOffsets( p, 1, p, 3 ); - const rangeB = Range.createFromParentsAndOffsets( p, 0, p, 2 ); + const rangeA = new Range( Position._createAt( p, 1 ), Position._createAt( p, 3 ) ); + const rangeB = new Range( Position._createAt( p, 0 ), Position._createAt( p, 2 ) ); model.change( () => { attribute( rangeA, 'a', null, true ); @@ -1110,28 +1110,28 @@ describe( 'Differ', () => { expectChanges( [ { type, - range: Range.createFromParentsAndOffsets( p, 0, p, 1 ), + range: new Range( Position._createAt( p, 0 ), Position._createAt( p, 1 ) ), attributeKey: 'b', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 1, p, 2 ), + range: new Range( Position._createAt( p, 1 ), Position._createAt( p, 2 ) ), attributeKey: 'a', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 1, p, 2 ), + range: new Range( Position._createAt( p, 1 ), Position._createAt( p, 2 ) ), attributeKey: 'b', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 2, p, 3 ), + range: new Range( Position._createAt( p, 2 ), Position._createAt( p, 3 ) ), attributeKey: 'a', attributeOldValue, attributeNewValue @@ -1143,8 +1143,8 @@ describe( 'Differ', () => { it( 'on already changed nodes', () => { const p = root.getChild( 1 ); - const rangeA = Range.createFromParentsAndOffsets( p, 0, p, 3 ); - const rangeB = Range.createFromParentsAndOffsets( p, 1, p, 2 ); + const rangeA = new Range( Position._createAt( p, 0 ), Position._createAt( p, 3 ) ); + const rangeB = new Range( Position._createAt( p, 1 ), Position._createAt( p, 2 ) ); model.change( () => { attribute( rangeA, 'a', null, true ); @@ -1158,21 +1158,21 @@ describe( 'Differ', () => { expectChanges( [ { type, - range: Range.createFromParentsAndOffsets( p, 0, p, 2 ), + range: new Range( Position._createAt( p, 0 ), Position._createAt( p, 2 ) ), attributeKey: 'a', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 1, p, 2 ), + range: new Range( Position._createAt( p, 1 ), Position._createAt( p, 2 ) ), attributeKey: 'b', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 2, p, 3 ), + range: new Range( Position._createAt( p, 2 ), Position._createAt( p, 3 ) ), attributeKey: 'a', attributeOldValue, attributeNewValue @@ -1184,8 +1184,8 @@ describe( 'Differ', () => { it( 'on some changed and some not changed nodes', () => { const p = root.getChild( 1 ); - const rangeA = Range.createFromParentsAndOffsets( p, 0, p, 2 ); - const rangeB = Range.createFromParentsAndOffsets( p, 1, p, 3 ); + const rangeA = new Range( Position._createAt( p, 0 ), Position._createAt( p, 2 ) ); + const rangeB = new Range( Position._createAt( p, 1 ), Position._createAt( p, 3 ) ); model.change( () => { attribute( rangeA, 'a', null, true ); @@ -1198,14 +1198,14 @@ describe( 'Differ', () => { expectChanges( [ { type, - range: Range.createFromParentsAndOffsets( p, 0, p, 2 ), + range: new Range( Position._createAt( p, 0 ), Position._createAt( p, 2 ) ), attributeKey: 'a', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 1, p, 3 ), + range: new Range( Position._createAt( p, 1 ), Position._createAt( p, 3 ) ), attributeKey: 'b', attributeOldValue, attributeNewValue @@ -1217,8 +1217,8 @@ describe( 'Differ', () => { it( 'over all changed nodes and some not changed nodes', () => { const p = root.getChild( 0 ); - const rangeA = Range.createFromParentsAndOffsets( p, 1, p, 2 ); - const rangeB = Range.createFromParentsAndOffsets( p, 0, p, 3 ); + const rangeA = new Range( Position._createAt( p, 1 ), Position._createAt( p, 2 ) ); + const rangeB = new Range( Position._createAt( p, 0 ), Position._createAt( p, 3 ) ); model.change( () => { attribute( rangeA, 'a', null, true ); @@ -1232,21 +1232,21 @@ describe( 'Differ', () => { expectChanges( [ { type, - range: Range.createFromParentsAndOffsets( p, 0, p, 1 ), + range: new Range( Position._createAt( p, 0 ), Position._createAt( p, 1 ) ), attributeKey: 'b', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 1, p, 2 ), + range: new Range( Position._createAt( p, 1 ), Position._createAt( p, 2 ) ), attributeKey: 'a', attributeOldValue, attributeNewValue }, { type, - range: Range.createFromParentsAndOffsets( p, 1, p, 3 ), + range: new Range( Position._createAt( p, 1 ), Position._createAt( p, 3 ) ), attributeKey: 'b', attributeOldValue, attributeNewValue @@ -1391,8 +1391,8 @@ describe( 'Differ', () => { let range, rangeB; beforeEach( () => { - range = Range.createFromParentsAndOffsets( root, 0, root, 1 ); - rangeB = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + range = new Range( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ); + rangeB = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); } ); it( 'add marker', () => { @@ -1603,10 +1603,10 @@ describe( 'Differ', () => { it( 'remove is correctly transformed by multiple affecting changes', () => { root._appendChild( new Element( 'paragraph', null, new Text( 'xyz' ) ) ); - model.change( () => { + model.change( writer => { rename( root.getChild( 1 ), 'heading' ); rename( root.getChild( 2 ), 'heading' ); - remove( Position.createAt( root, 0 ), 3 ); + remove( writer.createPositionAt( root, 0 ), 3 ); expectChanges( [ { type: 'remove', name: 'paragraph', length: 1, position: new Position( root, [ 0 ] ) }, @@ -1624,8 +1624,8 @@ describe( 'Differ', () => { position = new Position( root, [ 0, 1 ] ); p1 = root.getChild( 0 ); - range = Range.createFromParentsAndOffsets( p1, 2, p1, 4 ); - rangeAttrChange = Range.createFromParentsAndOffsets( p1, 3, p1, 4 ); + range = new Range( Position._createAt( p1, 2 ), Position._createAt( p1, 4 ) ); + rangeAttrChange = new Range( Position._createAt( p1, 3 ), Position._createAt( p1, 4 ) ); } ); it( 'should return changes in graveyard if a flag was set up', () => { @@ -1762,7 +1762,7 @@ describe( 'Differ', () => { } function remove( sourcePosition, howMany ) { - const targetPosition = Position.createAt( doc.graveyard, doc.graveyard.maxOffset ); + const targetPosition = Position._createAt( doc.graveyard, doc.graveyard.maxOffset ); const operation = new MoveOperation( sourcePosition, howMany, targetPosition, doc.version ); model.applyOperation( operation ); @@ -1775,7 +1775,7 @@ describe( 'Differ', () => { } function rename( element, newName ) { - const operation = new RenameOperation( Position.createBefore( element ), element.name, newName, doc.version ); + const operation = new RenameOperation( Position._createBefore( element ), element.name, newName, doc.version ); model.applyOperation( operation ); } diff --git a/tests/model/document.js b/tests/model/document.js index 38cf407dd..42dc082e1 100644 --- a/tests/model/document.js +++ b/tests/model/document.js @@ -8,7 +8,6 @@ import Document from '../../src/model/document'; import RootElement from '../../src/model/rootelement'; import Text from '../../src/model/text'; import Batch from '../../src/model/batch'; -import Range from '../../src/model/range'; import Collection from '@ckeditor/ckeditor5-utils/src/collection'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import count from '@ckeditor/ckeditor5-utils/src/count'; @@ -228,7 +227,7 @@ describe( 'Document', () => { sinon.spy( doc.differ, 'bufferMarkerChange' ); model.change( writer => { - const range = Range.createCollapsedAt( doc.getRoot(), 0 ); + const range = writer.createRange( writer.createPositionAt( doc.getRoot(), 0 ) ); writer.addMarker( 'marker', { range, usingOperation: false } ); } ); @@ -324,7 +323,7 @@ describe( 'Document', () => { doc.on( 'change', spy ); model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( root, 2, root, 2 ) ); + writer.setSelection( root, 2 ); } ); sinon.assert.calledOnce( spy ); @@ -373,7 +372,7 @@ describe( 'Document', () => { doc.on( 'change:data', spy ); model.change( writer => { - writer.setSelection( Range.createFromParentsAndOffsets( root, 2, root, 2 ) ); + writer.setSelection( root, 2 ); } ); sinon.assert.notCalled( spy ); @@ -388,7 +387,7 @@ describe( 'Document', () => { doc.on( 'change:data', spy ); model.change( writer => { - const range = Range.createFromParentsAndOffsets( root, 2, root, 4 ); + const range = writer.createRange( writer.createPositionAt( root, 2 ), writer.createPositionAt( root, 4 ) ); writer.addMarker( 'name', { range, usingOperation: true, affectsData: true } ); } ); @@ -404,7 +403,7 @@ describe( 'Document', () => { doc.on( 'change:data', spy ); model.change( writer => { - const range = Range.createFromParentsAndOffsets( root, 2, root, 4 ); + const range = writer.createRange( writer.createPositionAt( root, 2 ), writer.createPositionAt( root, 4 ) ); writer.addMarker( 'name', { range, usingOperation: true } ); } ); @@ -420,7 +419,7 @@ describe( 'Document', () => { doc.on( 'change:data', spy ); model.change( writer => { - const range = Range.createFromParentsAndOffsets( root, 2, root, 4 ); + const range = writer.createRange( writer.createPositionAt( root, 2 ), writer.createPositionAt( root, 4 ) ); writer.addMarker( 'name', { range, usingOperation: false, affectsData: true } ); } ); @@ -436,7 +435,7 @@ describe( 'Document', () => { doc.on( 'change:data', spy ); model.change( writer => { - const range = Range.createFromParentsAndOffsets( root, 2, root, 4 ); + const range = writer.createRange( writer.createPositionAt( root, 2 ), writer.createPositionAt( root, 4 ) ); writer.addMarker( 'name', { range, usingOperation: false } ); } ); @@ -471,7 +470,7 @@ describe( 'Document', () => { doc.on( 'change', changeSpy ); model.change( writer => { - const range = Range.createFromParentsAndOffsets( root, 2, root, 4 ); + const range = writer.createRange( writer.createPositionAt( root, 2 ), writer.createPositionAt( root, 4 ) ); writer.addMarker( 'name', { range, usingOperation: false } ); } ); diff --git a/tests/model/documentselection.js b/tests/model/documentselection.js index a77ada163..b3594f304 100644 --- a/tests/model/documentselection.js +++ b/tests/model/documentselection.js @@ -257,7 +257,7 @@ describe( 'DocumentSelection', () => { describe( '_setFocus()', () => { it( 'modifies default range', () => { const startPos = selection.getFirstPosition(); - const endPos = Position.createAt( root, 'end' ); + const endPos = Position._createAt( root, 'end' ); selection._setFocus( endPos ); @@ -266,9 +266,9 @@ describe( 'DocumentSelection', () => { } ); it( 'detaches the range it replaces', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); - const newEndPos = Position.createAt( root, 4 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 2 ); + const newEndPos = Position._createAt( root, 4 ); const spy = testUtils.sinon.spy( LiveRange.prototype, 'detach' ); selection._setTo( new Range( startPos, endPos ) ); @@ -281,7 +281,7 @@ describe( 'DocumentSelection', () => { it( 'refreshes attributes', () => { const spy = sinon.spy( selection._selection, '_updateAttributes' ); - selection._setFocus( Position.createAt( root, 1 ) ); + selection._setFocus( Position._createAt( root, 1 ) ); expect( spy.called ).to.be.true; } ); @@ -379,7 +379,7 @@ describe( 'DocumentSelection', () => { setData( model, 'f<$text italic="true">[o<$text bold="true">ob]ar' ); - selection._setTo( [ Range.createFromPositionAndShift( selection.getLastRange().end, 0 ) ] ); + selection._setTo( [ Range._createFromPositionAndShift( selection.getLastRange().end, 0 ) ] ); expect( selection.getAttribute( 'bold' ) ).to.equal( true ); expect( selection.hasAttribute( 'italic' ) ).to.equal( false ); @@ -447,7 +447,7 @@ describe( 'DocumentSelection', () => { // Trigger selecton auto update on document change. It should not get attribute from surrounding text; model.change( writer => { - writer.setAttribute( 'foo', 'bar', Range.createIn( fullP ) ); + writer.setAttribute( 'foo', 'bar', Range._createIn( fullP ) ); } ); expect( selection.getAttribute( 'foo' ) ).to.be.undefined; @@ -656,7 +656,7 @@ describe( 'DocumentSelection', () => { selection._setAttribute( 'foo', 'bar' ); model.change( writer => { - writer.move( Range.createOn( fullP.getChild( 0 ) ), rangeInEmptyP.start ); + writer.move( writer.createRangeOn( fullP.getChild( 0 ) ), rangeInEmptyP.start ); } ); expect( emptyP.hasAttribute( fooStoreAttrKey ) ).to.be.false; @@ -671,7 +671,7 @@ describe( 'DocumentSelection', () => { model.change( writer => { // {} - writer.merge( Position.createAfter( emptyP ) ); + writer.merge( writer.createPositionAfter( emptyP ) ); } ); expect( emptyP.hasAttribute( fooStoreAttrKey ) ).to.be.false; @@ -717,7 +717,7 @@ describe( 'DocumentSelection', () => { model.change( writer => { // {} - writer.merge( Position.createAfter( emptyP ) ); + writer.merge( writer.createPositionAfter( emptyP ) ); } ); expect( emptyP.getAttribute( fooStoreAttrKey ) ).to.equal( 'bar' ); @@ -1210,8 +1210,8 @@ describe( 'DocumentSelection', () => { ] ); selection._setTo( [ - Range.createIn( root.getNodeByPath( [ 0 ] ) ), - Range.createIn( root.getNodeByPath( [ 1 ] ) ) + Range._createIn( root.getNodeByPath( [ 0 ] ) ), + Range._createIn( root.getNodeByPath( [ 1 ] ) ) ] ); spyRange = sinon.spy(); @@ -1234,11 +1234,11 @@ describe( 'DocumentSelection', () => { root._appendChild( '\uD83D\uDCA9' ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 0, root, 1 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 1, root, 2 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); } ); @@ -1247,27 +1247,27 @@ describe( 'DocumentSelection', () => { root._appendChild( 'foo̻̐ͩbar' ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 3, root, 9 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 3 ), Position._createAt( root, 9 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 4, root, 9 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 4 ), Position._createAt( root, 9 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 5, root, 9 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 5 ), Position._createAt( root, 9 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 1, root, 3 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 1 ), Position._createAt( root, 3 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 1, root, 4 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 1 ), Position._createAt( root, 4 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); expect( () => { - doc.selection._setTo( Range.createFromParentsAndOffsets( root, 1, root, 5 ) ); + doc.selection._setTo( new Range( Position._createAt( root, 1 ), Position._createAt( root, 5 ) ) ); } ).to.throw( CKEditorError, /document-selection-wrong-position/ ); } ); } ); diff --git a/tests/model/liveposition.js b/tests/model/liveposition.js index a979119b9..b097a249f 100644 --- a/tests/model/liveposition.js +++ b/tests/model/liveposition.js @@ -12,7 +12,8 @@ import LivePosition from '../../src/model/liveposition'; import Range from '../../src/model/range'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; -describe( 'LivePosition', () => { +describe( 'LivePosition', () => +{ let model, doc, root, ul, p, li1, li2; beforeEach( () => { @@ -68,26 +69,22 @@ describe( 'LivePosition', () => { LivePosition.prototype.stopListening.restore(); } ); - it( 'createFromPosition should return LivePosition', () => { - const position = LivePosition.createFromPosition( new Position( root, [ 0 ] ) ); - expect( position ).to.be.instanceof( LivePosition ); - position.detach(); - } ); - - it( 'createFromParentAndOffset should return LivePosition', () => { - const position = LivePosition.createFromParentAndOffset( ul, 0 ); - expect( position ).to.be.instanceof( LivePosition ); - position.detach(); + describe( 'fromPosition()', () => { + it( 'should return LivePosition', () => { + const position = LivePosition.fromPosition( new Position( root, [ 0 ] ) ); + expect( position ).to.be.instanceof( LivePosition ); + position.detach(); + } ); } ); - it( 'createBefore should return LivePosition', () => { - const position = LivePosition.createBefore( ul ); + it( '_createBefore should return LivePosition', () => { + const position = LivePosition._createBefore( ul ); expect( position ).to.be.instanceof( LivePosition ); position.detach(); } ); - it( 'createAfter should return LivePosition', () => { - const position = LivePosition.createAfter( ul ); + it( '_createAfter should return LivePosition', () => { + const position = LivePosition._createAfter( ul ); expect( position ).to.be.instanceof( LivePosition ); position.detach(); } ); @@ -140,7 +137,7 @@ describe( 'LivePosition', () => { it( 'is at the same parent and closer offset', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 0, 1 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 1, 1, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -154,7 +151,7 @@ describe( 'LivePosition', () => { live.stickiness = 'toNext'; model.change( writer => { const sourcePosition = new Position( root, [ 1, 0, 1 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 1, 1, 3 ] ); writer.move( sourceRange, targetPosition ); @@ -167,7 +164,7 @@ describe( 'LivePosition', () => { it( 'is at a position before a node from the live position path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 0, 1 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( root, [ 1, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -180,7 +177,7 @@ describe( 'LivePosition', () => { it( 'is from the same parent and closer offset', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 1, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( root, [ 1, 0, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -193,7 +190,7 @@ describe( 'LivePosition', () => { it( 'is from a position before a node from the live position path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 1, 2 ] ); writer.move( sourceRange, targetPosition ); @@ -206,7 +203,7 @@ describe( 'LivePosition', () => { it( 'contains live position (same level)', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 1, 2 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( root, [ 1, 0, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -219,7 +216,7 @@ describe( 'LivePosition', () => { it( 'contains live position (deep)', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 1 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 1, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -295,7 +292,7 @@ describe( 'LivePosition', () => { it( 'is at the same parent and further offset', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 0, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 1, 1, 6 ] ); writer.move( sourceRange, targetPosition ); @@ -312,7 +309,7 @@ describe( 'LivePosition', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 0, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 1, 1, 3 ] ); writer.move( sourceRange, targetPosition ); @@ -327,7 +324,7 @@ describe( 'LivePosition', () => { it( 'is at a position after a node from the live position path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 0, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 2 ] ); writer.move( sourceRange, targetPosition ); @@ -340,7 +337,7 @@ describe( 'LivePosition', () => { it( 'is from the same parent and further offset', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 1, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( otherRoot, [ 0 ] ); writer.move( sourceRange, targetPosition ); @@ -357,7 +354,7 @@ describe( 'LivePosition', () => { model.change( writer => { const sourcePosition = new Position( root, [ 1, 1 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( otherRoot, [ 0 ] ); writer.move( sourceRange, targetPosition ); @@ -374,7 +371,7 @@ describe( 'LivePosition', () => { writer.insertText( 'foo', new Position( otherRoot, [ 0 ] ) ); const sourcePosition = new Position( otherRoot, [ 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( otherRoot, [ 3 ] ); writer.move( sourceRange, targetPosition ); diff --git a/tests/model/liverange.js b/tests/model/liverange.js index ceb8d90b9..e959d2578 100644 --- a/tests/model/liverange.js +++ b/tests/model/liverange.js @@ -67,33 +67,21 @@ describe( 'LiveRange', () => { LiveRange.prototype.stopListening.restore(); } ); - it( 'createIn should return LiveRange', () => { - const range = LiveRange.createIn( p ); + it( '_createIn should return LiveRange', () => { + const range = LiveRange._createIn( p ); expect( range ).to.be.instanceof( LiveRange ); range.detach(); } ); - it( 'createFromParentsAndOffsets should return LiveRange', () => { - const range = LiveRange.createFromParentsAndOffsets( root, 0, p, 2 ); - expect( range ).to.be.instanceof( LiveRange ); - range.detach(); - } ); - - it( 'createFromPositionAndShift should return LiveRange', () => { - const range = LiveRange.createFromPositionAndShift( new Position( root, [ 0, 1 ] ), 4 ); - expect( range ).to.be.instanceof( LiveRange ); - range.detach(); - } ); - - it( 'createFromRange should return LiveRange', () => { - const range = LiveRange.createFromRange( new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) ) ); + it( '_createFromPositionAndShift should return LiveRange', () => { + const range = LiveRange._createFromPositionAndShift( new Position( root, [ 0, 1 ] ), 4 ); expect( range ).to.be.instanceof( LiveRange ); range.detach(); } ); it( 'should fire change:range event with when its boundaries are changed', () => { const live = new LiveRange( new Position( root, [ 0, 1, 4 ] ), new Position( root, [ 0, 2, 2 ] ) ); - const copy = Range.createFromRange( live ); + const copy = live.toRange(); const spy = sinon.spy(); live.on( 'change:range', spy ); @@ -102,7 +90,7 @@ describe( 'LiveRange', () => { const targetPosition = new Position( root, [ 0 ] ); model.change( writer => { - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); writer.move( sourceRange, targetPosition ); } ); @@ -126,7 +114,7 @@ describe( 'LiveRange', () => { const targetPosition = new Position( root, [ 0, 4, 0 ] ); model.change( writer => { - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); writer.move( sourceRange, targetPosition ); } ); @@ -149,7 +137,7 @@ describe( 'LiveRange', () => { const sourcePosition = new Position( root, [ 0, 0 ] ); model.change( writer => { - writer.remove( Range.createFromPositionAndShift( sourcePosition, 6 ) ); + writer.remove( Range._createFromPositionAndShift( sourcePosition, 6 ) ); } ); // Second parameter is deletion position. @@ -267,7 +255,7 @@ describe( 'LiveRange', () => { it( 'is to the same parent as range start and before it', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 4 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 4 ); const targetPosition = new Position( root, [ 0, 1, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -281,7 +269,7 @@ describe( 'LiveRange', () => { it( 'is to the same parent as range end and before it', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 4 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 4 ); const targetPosition = new Position( root, [ 0, 2, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -295,7 +283,7 @@ describe( 'LiveRange', () => { it( 'is to a position before a node from range start path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( root, [ 0, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -309,7 +297,7 @@ describe( 'LiveRange', () => { it( 'is to a position before a node from range end path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 0, 2 ] ); writer.move( sourceRange, targetPosition ); @@ -323,7 +311,7 @@ describe( 'LiveRange', () => { it( 'is from the same parent as range start and before it', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -337,7 +325,7 @@ describe( 'LiveRange', () => { it( 'is from the same parent as range end and before it - #1', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 2, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -351,7 +339,7 @@ describe( 'LiveRange', () => { it( 'is from the same parent as range end and before it - #2', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 2, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -365,7 +353,7 @@ describe( 'LiveRange', () => { it( 'is from a position before a node from range start path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 0, 4 ] ); writer.move( sourceRange, targetPosition ); @@ -379,7 +367,7 @@ describe( 'LiveRange', () => { it( 'intersects on live range left side', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 2 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 4 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 4 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -393,7 +381,7 @@ describe( 'LiveRange', () => { it( 'intersects on live range right side', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 2, 1 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 4 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 4 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -409,7 +397,7 @@ describe( 'LiveRange', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -425,7 +413,7 @@ describe( 'LiveRange', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 3 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 5 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 5 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -441,7 +429,7 @@ describe( 'LiveRange', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 2 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 0, 1, 8 ] ); writer.move( sourceRange, targetPosition ); @@ -455,7 +443,7 @@ describe( 'LiveRange', () => { it( 'is intersecting with live range on right and is moved into live range', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 2, 1 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 5 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 5 ); const targetPosition = new Position( root, [ 0, 2, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -663,7 +651,7 @@ describe( 'LiveRange', () => { beforeEach( () => { live = new LiveRange( new Position( root, [ 0, 1, 4 ] ), new Position( root, [ 0, 2, 2 ] ) ); - clone = Range.createFromRange( live ); + clone = live.toRange(); spy = sinon.spy(); live.on( 'change:content', spy ); @@ -688,7 +676,7 @@ describe( 'LiveRange', () => { it( 'inside the range', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 0, 1, 5 ] ); writer.move( sourceRange, targetPosition ); @@ -701,7 +689,7 @@ describe( 'LiveRange', () => { it( 'from the range', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 5 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -714,7 +702,7 @@ describe( 'LiveRange', () => { it( 'from the beginning of range', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 2 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 2 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -729,7 +717,7 @@ describe( 'LiveRange', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 1, 5 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 0, 1, 7 ] ); writer.move( sourceRange, targetPosition ); @@ -748,7 +736,7 @@ describe( 'LiveRange', () => { beforeEach( () => { otherRoot = doc.createRoot( '$root', 'otherRoot' ); live = new LiveRange( new Position( root, [ 0, 1, 4 ] ), new Position( root, [ 0, 2, 2 ] ) ); - clone = Range.createFromRange( live ); + clone = live.toRange(); spy = sinon.spy(); live.on( 'change', spy ); @@ -791,7 +779,7 @@ describe( 'LiveRange', () => { it( 'is to the same parent as range end and after it', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4, 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 0, 2, 4 ] ); writer.move( sourceRange, targetPosition ); @@ -804,7 +792,7 @@ describe( 'LiveRange', () => { it( 'is to a position after a node from range end path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 5 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 0, 4 ] ); writer.move( sourceRange, targetPosition ); @@ -817,7 +805,7 @@ describe( 'LiveRange', () => { it( 'is from the same parent as range end and after it', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 2, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 3 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 3 ); const targetPosition = new Position( root, [ 0, 4, 0 ] ); writer.move( sourceRange, targetPosition ); @@ -830,7 +818,7 @@ describe( 'LiveRange', () => { it( 'is from a position after a node from range end path', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 0, 5 ] ); writer.move( sourceRange, targetPosition ); @@ -843,7 +831,7 @@ describe( 'LiveRange', () => { it( 'is to different root', () => { model.change( writer => { const sourcePosition = new Position( root, [ 0, 4 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( otherRoot, [ 0 ] ); writer.move( sourceRange, targetPosition ); @@ -858,7 +846,7 @@ describe( 'LiveRange', () => { writer.insertText( 'foo', new Position( otherRoot, [ 0 ] ) ); const sourcePosition = new Position( otherRoot, [ 0 ] ); - const sourceRange = Range.createFromPositionAndShift( sourcePosition, 1 ); + const sourceRange = Range._createFromPositionAndShift( sourcePosition, 1 ); const targetPosition = new Position( root, [ 0, 4 ] ); writer.move( sourceRange, targetPosition ); diff --git a/tests/model/markercollection.js b/tests/model/markercollection.js index a2f8b8dfc..7887226f4 100644 --- a/tests/model/markercollection.js +++ b/tests/model/markercollection.js @@ -21,8 +21,8 @@ describe( 'MarkerCollection', () => { markers = new MarkerCollection(); root = doc.createRoot(); - range = Range.createFromParentsAndOffsets( root, 0, root, 1 ); - range2 = Range.createFromParentsAndOffsets( root, 0, root, 2 ); + range = new Range( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ); + range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 2 ) ); } ); describe( 'iterator', () => { @@ -212,7 +212,7 @@ describe( 'MarkerCollection', () => { markers._set( 'a', range ); const markerB = markers._set( 'b', range2 ); - const result = Array.from( markers.getMarkersAtPosition( Position.createAt( root, 1 ) ) ); + const result = Array.from( markers.getMarkersAtPosition( Position._createAt( root, 1 ) ) ); expect( result ).to.deep.equal( [ markerB ] ); } ); @@ -250,7 +250,7 @@ describe( 'Marker', () => { it( 'should provide API that returns up-to-date marker range parameters', () => { root._appendChild( new Text( 'foo' ) ); - const range = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); const marker = model.markers._set( 'name', range ); expect( marker.getRange().isEqual( range ) ).to.be.true; @@ -261,7 +261,7 @@ describe( 'Marker', () => { writer.insertText( 'abc', root ); } ); - const updatedRange = Range.createFromParentsAndOffsets( root, 4, root, 5 ); + const updatedRange = new Range( Position._createAt( root, 4 ), Position._createAt( root, 5 ) ); expect( marker.getRange().isEqual( updatedRange ) ).to.be.true; expect( marker.getStart().isEqual( updatedRange.start ) ).to.be.true; @@ -269,7 +269,7 @@ describe( 'Marker', () => { } ); it( 'should throw when using the API if marker was removed from markers collection', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); const marker = model.markers._set( 'name', range ); model.markers._remove( 'name' ); @@ -296,7 +296,7 @@ describe( 'Marker', () => { } ); it( 'should attach live range to marker', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); const marker = model.markers._set( 'name', range ); const eventRange = sinon.spy(); @@ -313,7 +313,7 @@ describe( 'Marker', () => { } ); it( 'should detach live range from marker', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); const marker = model.markers._set( 'name', range ); const liveRange = marker._liveRange; @@ -335,10 +335,10 @@ describe( 'Marker', () => { } ); it( 'should reattach live range to marker', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); const marker = model.markers._set( 'name', range ); const oldLiveRange = marker._liveRange; - const newLiveRange = LiveRange.createFromParentsAndOffsets( root, 0, root, 1 ); + const newLiveRange = new LiveRange( Position._createAt( root, 0 ), Position._createAt( root, 1 ) ); const eventRange = sinon.spy(); const eventContent = sinon.spy(); @@ -364,7 +364,7 @@ describe( 'Marker', () => { } ); it( 'should change managedUsingOperations flag', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); const marker = model.markers._set( 'name', range, false ); expect( marker.managedUsingOperations ).to.be.false; @@ -379,7 +379,7 @@ describe( 'Marker', () => { } ); it( 'should change affectsData flag', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); const marker = model.markers._set( 'name', range, false, false ); expect( marker.affectsData ).to.be.false; diff --git a/tests/model/model.js b/tests/model/model.js index 1a3627797..ac44e0e8d 100644 --- a/tests/model/model.js +++ b/tests/model/model.js @@ -7,8 +7,10 @@ import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin'; import Model from '../../src/model/model'; import ModelText from '../../src/model/text'; import ModelRange from '../../src/model/range'; +import ModelPosition from '../../src/model/position'; import ModelSelection from '../../src/model/selection'; import ModelDocumentFragment from '../../src/model/documentfragment'; +import Batch from '../../src/model/batch'; import { getData, setData, stringify } from '../../src/dev-utils/model'; describe( 'Model', () => { @@ -539,38 +541,107 @@ describe( 'Model', () => { } ); it( 'should return true if there is a text node in given range', () => { - const range = ModelRange.createFromParentsAndOffsets( root, 1, root, 2 ); + const range = new ModelRange( ModelPosition._createAt( root, 1 ), ModelPosition._createAt( root, 2 ) ); expect( model.hasContent( range ) ).to.be.true; } ); it( 'should return true if there is a part of text node in given range', () => { const pFoo = root.getChild( 1 ); - const range = ModelRange.createFromParentsAndOffsets( pFoo, 1, pFoo, 2 ); + const range = new ModelRange( ModelPosition._createAt( pFoo, 1 ), ModelPosition._createAt( pFoo, 2 ) ); expect( model.hasContent( range ) ).to.be.true; } ); it( 'should return true if there is element that is an object in given range', () => { const divImg = root.getChild( 2 ); - const range = ModelRange.createFromParentsAndOffsets( divImg, 0, divImg, 1 ); + const range = new ModelRange( ModelPosition._createAt( divImg, 0 ), ModelPosition._createAt( divImg, 1 ) ); expect( model.hasContent( range ) ).to.be.true; } ); it( 'should return false if range is collapsed', () => { - const range = ModelRange.createFromParentsAndOffsets( root, 1, root, 1 ); + const range = new ModelRange( ModelPosition._createAt( root, 1 ), ModelPosition._createAt( root, 1 ) ); expect( model.hasContent( range ) ).to.be.false; } ); it( 'should return false if range has only elements that are not objects', () => { - const range = ModelRange.createFromParentsAndOffsets( root, 0, root, 1 ); + const range = new ModelRange( ModelPosition._createAt( root, 0 ), ModelPosition._createAt( root, 1 ) ); expect( model.hasContent( range ) ).to.be.false; } ); } ); + describe( 'createPositionFromPath()', () => { + it( 'should return instance of Position', () => { + expect( model.createPositionFromPath( model.document.getRoot(), [ 0 ] ) ).to.be.instanceof( ModelPosition ); + } ); + } ); + + describe( 'createPositionAt()', () => { + it( 'should return instance of Position', () => { + expect( model.createPositionAt( model.document.getRoot(), 0 ) ).to.be.instanceof( ModelPosition ); + } ); + } ); + + describe( 'createPositionAfter()', () => { + it( 'should return instance of Position', () => { + schema.register( 'paragraph', { inheritAllFrom: '$block' } ); + setData( model, 'fo[]ar' ); + + expect( model.createPositionAfter( model.document.getRoot().getChild( 0 ) ) ).to.be.instanceof( ModelPosition ); + } ); + } ); + + describe( 'createPositionBefore()', () => { + it( 'should return instance of Position', () => { + schema.register( 'paragraph', { inheritAllFrom: '$block' } ); + setData( model, 'fo[]ar' ); + + expect( model.createPositionBefore( model.document.getRoot().getChild( 0 ) ) ).to.be.instanceof( ModelPosition ); + } ); + } ); + + describe( 'createRange()', () => { + it( 'should return instance of Range', () => { + schema.register( 'paragraph', { inheritAllFrom: '$block' } ); + setData( model, 'fo[]ar' ); + + expect( model.createRange( model.createPositionAt( model.document.getRoot(), 0 ) ) ).to.be.instanceof( ModelRange ); + } ); + } ); + + describe( 'createRangeIn()', () => { + it( 'should return instance of Range', () => { + schema.register( 'paragraph', { inheritAllFrom: '$block' } ); + setData( model, 'fo[]ar' ); + + expect( model.createRangeIn( model.document.getRoot().getChild( 0 ) ) ).to.be.instanceof( ModelRange ); + } ); + } ); + + describe( 'createRangeOn()', () => { + it( 'should return instance of Range', () => { + schema.register( 'paragraph', { inheritAllFrom: '$block' } ); + setData( model, 'fo[]ar' ); + + expect( model.createRangeOn( model.document.getRoot().getChild( 0 ) ) ).to.be.instanceof( ModelRange ); + } ); + } ); + + describe( 'createSelection()', () => { + it( 'should return instance of Selection', () => { + expect( model.createSelection() ).to.be.instanceof( ModelSelection ); + } ); + } ); + + describe( 'createBatch()', () => { + it( 'should return instance of Batch', () => { + expect( model.createBatch() ).to.be.instanceof( Batch ); + } ); + } ); + describe( 'destroy()', () => { it( 'should destroy document', () => { sinon.spy( model.document, 'destroy' ); diff --git a/tests/model/operation/detachoperation.js b/tests/model/operation/detachoperation.js index 52632f122..26d2ec609 100644 --- a/tests/model/operation/detachoperation.js +++ b/tests/model/operation/detachoperation.js @@ -21,13 +21,13 @@ describe( 'DetachOperation', () => { } ); it( 'should have type equal to detach', () => { - const op = new DetachOperation( Position.createBefore( element ), 1 ); + const op = new DetachOperation( Position._createBefore( element ), 1 ); expect( op.type ).to.equal( 'detach' ); } ); it( 'should remove given element from parent', () => { - const op = new DetachOperation( Position.createBefore( element ), 1 ); + const op = new DetachOperation( Position._createBefore( element ), 1 ); model.applyOperation( op ); @@ -41,7 +41,7 @@ describe( 'DetachOperation', () => { root._appendChild( [ element ] ); - const op = new DetachOperation( Position.createBefore( element ), 1 ); + const op = new DetachOperation( Position._createBefore( element ), 1 ); expect( () => { op._validate(); @@ -50,14 +50,14 @@ describe( 'DetachOperation', () => { } ); it( 'should be not a document operation', () => { - const op = new DetachOperation( Position.createBefore( element ), 1 ); + const op = new DetachOperation( Position._createBefore( element ), 1 ); expect( op.isDocumentOperation ).to.false; } ); describe( 'toJSON', () => { it( 'should create proper json object', () => { - const position = Position.createBefore( element ); + const position = Position._createBefore( element ); const op = new DetachOperation( position, 1 ); const serialized = op.toJSON(); diff --git a/tests/model/operation/markeroperation.js b/tests/model/operation/markeroperation.js index a277885c0..5ffaf5e20 100644 --- a/tests/model/operation/markeroperation.js +++ b/tests/model/operation/markeroperation.js @@ -5,7 +5,6 @@ import Model from '../../../src/model/model'; import Text from '../../../src/model/text'; -import Range from '../../../src/model/range'; import MarkerOperation from '../../../src/model/operation/markeroperation'; function matchRange( range ) { @@ -20,7 +19,7 @@ describe( 'MarkerOperation', () => { doc = model.document; root = doc.createRoot(); root._appendChild( new Text( 'foo' ) ); - range = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + range = model.createRange( model.createPositionAt( root, 0 ), model.createPositionAt( root, 0 ) ); } ); it( 'should have property type equal to "marker"', () => { @@ -45,7 +44,7 @@ describe( 'MarkerOperation', () => { new MarkerOperation( 'name', null, range, model.markers, true, doc.version ) ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 3 ); + const range2 = model.createRange( model.createPositionAt( root, 0 ), model.createPositionAt( root, 3 ) ); sinon.spy( model.markers, '_set' ); @@ -99,7 +98,7 @@ describe( 'MarkerOperation', () => { } ); it( 'should return MarkerOperation with swapped ranges as reverse operation', () => { - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 3 ); + const range2 = model.createRange( model.createPositionAt( root, 0 ), model.createPositionAt( root, 3 ) ); const op1 = new MarkerOperation( 'name', null, range, model.markers, true, doc.version ); const reversed1 = op1.getReversed(); diff --git a/tests/model/operation/renameoperation.js b/tests/model/operation/renameoperation.js index 82522be80..5bd890dd1 100644 --- a/tests/model/operation/renameoperation.js +++ b/tests/model/operation/renameoperation.js @@ -23,7 +23,7 @@ describe( 'RenameOperation', () => { element = new Element( oldName ); root._appendChild( element ); - position = Position.createBefore( element ); + position = Position._createBefore( element ); } ); it( 'should have type equal to rename', () => { @@ -64,7 +64,7 @@ describe( 'RenameOperation', () => { describe( '_validate()', () => { it( 'should throw an error if position is not before an element', () => { - const op = new RenameOperation( Position.createAt( root, 'end' ), oldName, newName, doc.version ); + const op = new RenameOperation( Position._createAt( root, 'end' ), oldName, newName, doc.version ); expect( () => { op._validate(); @@ -89,7 +89,7 @@ describe( 'RenameOperation', () => { } ); it( 'should create a RenameOperation with the same parameters when cloned', () => { - const op = new RenameOperation( Position.createAt( root, 'end' ), oldName, newName, doc.version ); + const op = new RenameOperation( Position._createAt( root, 'end' ), oldName, newName, doc.version ); const clone = op.clone(); // New instance rather than a pointer to the old instance. @@ -104,7 +104,7 @@ describe( 'RenameOperation', () => { describe( 'toJSON', () => { it( 'should create proper serialized object', () => { - const op = new RenameOperation( Position.createAt( root, 'end' ), oldName, newName, doc.version ); + const op = new RenameOperation( Position._createAt( root, 'end' ), oldName, newName, doc.version ); const serialized = op.toJSON(); expect( serialized ).to.deep.equal( { @@ -119,7 +119,7 @@ describe( 'RenameOperation', () => { describe( 'fromJSON', () => { it( 'should create proper AttributeOperation from json object', () => { - const op = new RenameOperation( Position.createAt( root, 'end' ), oldName, newName, doc.version ); + const op = new RenameOperation( Position._createAt( root, 'end' ), oldName, newName, doc.version ); const serialized = op.toJSON(); const deserialized = RenameOperation.fromJSON( serialized, doc ); diff --git a/tests/model/operation/transform.js b/tests/model/operation/transform.js index 97c8a76e1..23bba1554 100644 --- a/tests/model/operation/transform.js +++ b/tests/model/operation/transform.js @@ -100,7 +100,7 @@ describe( 'transform', () => { expected = { type: InsertOperation, - position: Position.createFromPosition( position ) + position: position.clone() }; } ); @@ -217,7 +217,7 @@ describe( 'transform', () => { describe( 'by AttributeOperation', () => { it( 'no position update', () => { const transformBy = new AttributeOperation( - Range.createFromPositionAndShift( position, 2 ), + Range._createFromPositionAndShift( position, 2 ), 'foo', null, 'bar', @@ -914,15 +914,15 @@ describe( 'transform', () => { targetPosition = new Position( root, [ 3, 3, 3 ] ); howMany = 2; - rangeEnd = Position.createFromPosition( sourcePosition ); + rangeEnd = sourcePosition.clone(); rangeEnd.offset += howMany; op = new MoveOperation( sourcePosition, howMany, targetPosition, 0 ); expected = { type: MoveOperation, - sourcePosition: Position.createFromPosition( sourcePosition ), - targetPosition: Position.createFromPosition( targetPosition ), + sourcePosition: sourcePosition.clone(), + targetPosition: targetPosition.clone(), howMany }; } ); @@ -1957,7 +1957,7 @@ describe( 'transform', () => { beforeEach( () => { transformBy = new MoveOperation( - Position.createFromPosition( op.sourcePosition ), + op.sourcePosition.clone(), op.howMany, new Position( doc.graveyard, [ 0 ] ), 0 @@ -2015,11 +2015,11 @@ describe( 'transform', () => { it( 'should force removing content even if was less important', () => { const op = new MoveOperation( new Position( root, [ 8 ] ), 2, new Position( doc.graveyard, [ 0 ] ), 0 ); - const targetPosition = Position.createFromPosition( op.targetPosition ); + const targetPosition = op.targetPosition.clone(); const transformBy = new MoveOperation( new Position( root, [ 8 ] ), 2, new Position( root, [ 1 ] ), 0 ); - const sourcePosition = Position.createFromPosition( transformBy.targetPosition ); + const sourcePosition = transformBy.targetPosition.clone(); const transOp = transform( op, transformBy ); @@ -2426,8 +2426,8 @@ describe( 'transform', () => { let oldRange, newRange; beforeEach( () => { - oldRange = Range.createFromParentsAndOffsets( root, 1, root, 4 ); - newRange = Range.createFromParentsAndOffsets( root, 10, root, 12 ); + oldRange = new Range( Position._createAt( root, 1 ), Position._createAt( root, 4 ) ); + newRange = new Range( Position._createAt( root, 10 ), Position._createAt( root, 12 ) ); op = new MarkerOperation( 'name', oldRange, newRange, model.markers, false, 0 ); expected = { @@ -2441,7 +2441,7 @@ describe( 'transform', () => { it( 'insert position affecting oldRange: update oldRange', () => { // Just CC things. op.newRange = null; - const transformBy = new InsertOperation( Position.createAt( root, 0 ), [ nodeA, nodeB ], 0 ); + const transformBy = new InsertOperation( Position._createAt( root, 0 ), [ nodeA, nodeB ], 0 ); const transOp = transform( op, transformBy ); @@ -2456,7 +2456,7 @@ describe( 'transform', () => { it( 'insert position affecting newRange: update newRange', () => { // Just CC things. op.oldRange = null; - const transformBy = new InsertOperation( Position.createAt( root, 8 ), [ nodeA, nodeB ], 0 ); + const transformBy = new InsertOperation( Position._createAt( root, 8 ), [ nodeA, nodeB ], 0 ); const transOp = transform( op, transformBy ); @@ -2494,7 +2494,7 @@ describe( 'transform', () => { // Just CC things. op.newRange = null; - const transformBy = new MoveOperation( Position.createAt( root, 0 ), 1, Position.createAt( root, 20 ), 0 ); + const transformBy = new MoveOperation( Position._createAt( root, 0 ), 1, Position._createAt( root, 20 ), 0 ); const transOp = transform( op, transformBy ); expected.newRange = null; @@ -2506,7 +2506,7 @@ describe( 'transform', () => { } ); it( 'moved range contains oldRange and is before newRange: update oldRange and newRange', () => { - const transformBy = new MoveOperation( Position.createAt( root, 2 ), 2, Position.createAt( root, 20 ), 0 ); + const transformBy = new MoveOperation( Position._createAt( root, 2 ), 2, Position._createAt( root, 20 ), 0 ); const transOp = transform( op, transformBy ); expected.oldRange.start.offset = 1; @@ -2522,7 +2522,7 @@ describe( 'transform', () => { // Just CC things. op.oldRange = null; - const transformBy = new MoveOperation( Position.createAt( root, 20 ), 2, Position.createAt( root, 11 ), 0 ); + const transformBy = new MoveOperation( Position._createAt( root, 20 ), 2, Position._createAt( root, 11 ), 0 ); const transOp = transform( op, transformBy ); expected.oldRange = null; @@ -2534,7 +2534,7 @@ describe( 'transform', () => { } ); it( 'target position is inside oldRange and before newRange: update oldRange and newRange', () => { - const transformBy = new MoveOperation( Position.createAt( root, 20 ), 4, Position.createAt( root, 2 ), 0 ); + const transformBy = new MoveOperation( Position._createAt( root, 20 ), 4, Position._createAt( root, 2 ), 0 ); const transOp = transform( op, transformBy ); expected.oldRange.start.offset = 1; @@ -2586,7 +2586,7 @@ describe( 'transform', () => { } ); it( 'same marker name and is important: convert to NoOperation', () => { - const anotherRange = Range.createFromParentsAndOffsets( root, 2, root, 2 ); + const anotherRange = new Range( Position._createAt( root, 2 ), Position._createAt( root, 2 ) ); const transformBy = new MarkerOperation( 'name', oldRange, anotherRange, model.markers, false, 0 ); const transOp = transform( op, transformBy ); @@ -2598,7 +2598,7 @@ describe( 'transform', () => { } ); it( 'same marker name and is less important: update oldRange parameter', () => { - const anotherRange = Range.createFromParentsAndOffsets( root, 2, root, 2 ); + const anotherRange = new Range( Position._createAt( root, 2 ), Position._createAt( root, 2 ) ); const transformBy = new MarkerOperation( 'name', oldRange, anotherRange, model.markers, false, 0 ); const transOp = transform( op, transformBy, strongContext ); diff --git a/tests/model/operation/transform/utils.js b/tests/model/operation/transform/utils.js index 0090c565c..f4ae0e073 100644 --- a/tests/model/operation/transform/utils.js +++ b/tests/model/operation/transform/utils.js @@ -54,7 +54,7 @@ export class Client { model.change( writer => { // Replace existing model in document by new one. - writer.remove( Range.createIn( modelRoot ) ); + writer.remove( writer.createRangeIn( modelRoot ) ); writer.insert( modelDocumentFragment, modelRoot ); } ); @@ -220,11 +220,11 @@ export class Client { switch ( type ) { default: case 'start': - return Position.createFromPosition( selRange.start ); + return selRange.start.clone(); case 'end': - return Position.createFromPosition( selRange.end ); + return selRange.end.clone(); case 'beforeParent': - return Position.createBefore( selRange.start.parent ); + return Position._createBefore( selRange.start.parent ); } } diff --git a/tests/model/operation/utils.js b/tests/model/operation/utils.js index e63975d5f..6d87f3bf0 100644 --- a/tests/model/operation/utils.js +++ b/tests/model/operation/utils.js @@ -39,19 +39,19 @@ describe( 'Operation utils', () => { describe( 'insert', () => { it( 'should insert nodes between nodes', () => { - utils._insert( Position.createAt( root, 3 ), [ 'xxx', new Element( 'p' ) ] ); + utils._insert( Position._createAt( root, 3 ), [ 'xxx', new Element( 'p' ) ] ); expectData( 'fooxxx

<$text bold="true">barxyz' ); } ); it( 'should split text node if nodes at inserted at offset inside text node', () => { - utils._insert( Position.createAt( root, 5 ), new Element( 'p' ) ); + utils._insert( Position._createAt( root, 5 ), new Element( 'p' ) ); expectData( 'foo<$text bold="true">ba

<$text bold="true">rxyz' ); } ); it( 'should merge text nodes if possible', () => { - utils._insert( Position.createAt( root, 3 ), new Text( 'xxx', { bold: true } ) ); + utils._insert( Position._createAt( root, 3 ), new Text( 'xxx', { bold: true } ) ); expectData( 'foo<$text bold="true">xxxbarxyz' ); } ); @@ -59,21 +59,21 @@ describe( 'Operation utils', () => { describe( 'remove', () => { it( 'should remove nodes in given range', () => { - const range = Range.createFromParentsAndOffsets( root, 3, root, 6 ); + const range = new Range( Position._createAt( root, 3 ), Position._createAt( root, 6 ) ); utils._remove( range ); expectData( 'fooxyz' ); } ); it( 'should split text node if range starts or ends inside text node', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 5 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 5 ) ); utils._remove( range ); expectData( 'f<$text bold="true">rxyz' ); } ); it( 'should merge text nodes if possible', () => { - const range = Range.createFromParentsAndOffsets( root, 3, root, 7 ); + const range = new Range( Position._createAt( root, 3 ), Position._createAt( root, 7 ) ); utils._remove( range ); expectData( 'fooxyz' ); @@ -89,15 +89,15 @@ describe( 'Operation utils', () => { describe( 'move', () => { it( 'should move a range of nodes', () => { - const range = Range.createFromParentsAndOffsets( root, 3, root, 6 ); - utils._move( range, Position.createAt( root, 0 ) ); + const range = new Range( Position._createAt( root, 3 ), Position._createAt( root, 6 ) ); + utils._move( range, Position._createAt( root, 0 ) ); expectData( '<$text bold="true">barfooxyz' ); } ); it( 'should correctly move if target position is in same element as moved range, but after range', () => { - const range = Range.createFromParentsAndOffsets( root, 3, root, 6 ); - utils._move( range, Position.createAt( root, 10 ) ); + const range = new Range( Position._createAt( root, 3 ), Position._createAt( root, 6 ) ); + utils._move( range, Position._createAt( root, 10 ) ); expectData( 'fooxyz<$text bold="true">bar' ); } ); @@ -111,21 +111,21 @@ describe( 'Operation utils', () => { describe( 'setAttribute', () => { it( 'should set attribute on given range of nodes', () => { - const range = Range.createFromParentsAndOffsets( root, 6, root, 8 ); + const range = new Range( Position._createAt( root, 6 ), Position._createAt( root, 8 ) ); utils._setAttribute( range, 'newAttr', true ); expectData( 'foo<$text bold="true">bar<$text newAttr="true">xyz' ); } ); it( 'should remove attribute if null was passed as a value', () => { - const range = Range.createFromParentsAndOffsets( root, 6, root, 7 ); + const range = new Range( Position._createAt( root, 6 ), Position._createAt( root, 7 ) ); utils._setAttribute( range, 'src', null ); expectData( 'foo<$text bold="true">barxyz' ); } ); it( 'should merge nodes if possible', () => { - const range = Range.createFromParentsAndOffsets( root, 0, root, 3 ); + const range = new Range( Position._createAt( root, 0 ), Position._createAt( root, 3 ) ); utils._setAttribute( range, 'bold', true ); expectData( '<$text bold="true">foobarxyz' ); diff --git a/tests/model/position.js b/tests/model/position.js index 03e7da8ab..924029ee8 100644 --- a/tests/model/position.js +++ b/tests/model/position.js @@ -19,6 +19,7 @@ import MergeOperation from '../../src/model/operation/mergeoperation'; import SplitOperation from '../../src/model/operation/splitoperation'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; +import LivePosition from '../../src/model/liveposition'; describe( 'Position', () => { let doc, model, root, otherRoot, p, ul, li1, li2, f, o, z, b, a, r, foz, bar; @@ -93,7 +94,7 @@ describe( 'Position', () => { const pos = new Position( li1, [ 0, 2 ] ); expect( pos ).to.have.property( 'root', root ); - expect( pos.isEqual( Position.createAt( li1, 0, 2 ) ) ); + expect( pos.isEqual( Position._createAt( li1, 0, 2 ) ) ); } ); it( 'should normalize Element from a detached branch as a root', () => { @@ -102,7 +103,7 @@ describe( 'Position', () => { const pos = new Position( elA, [ 0 ] ); expect( pos ).to.have.property( 'root', rootEl ); - expect( pos.isEqual( Position.createAt( elA, 0 ) ) ); + expect( pos.isEqual( Position._createAt( elA, 0 ) ) ); } ); it( 'should throw error if given path is incorrect', () => { @@ -126,129 +127,124 @@ describe( 'Position', () => { } ); } ); - describe( 'createFromParentAndOffset()', () => { - it( 'should create positions form node and offset', () => { - expect( Position.createFromParentAndOffset( root, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] ); - expect( Position.createFromParentAndOffset( root, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); - expect( Position.createFromParentAndOffset( root, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] ); + describe( 'static creators', () => { + describe( '_createAt()', () => { + it( 'should throw if no offset is passed', () => { + expect( () => Position._createAt( ul ) ).to.throw( CKEditorError, /model-createPositionAt-offset-required/ ); + } ); - expect( Position.createFromParentAndOffset( p, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 0, 0 ] ); + it( 'should create positions from positions', () => { + const position = Position._createAt( ul, 0 ); - expect( Position.createFromParentAndOffset( ul, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); - expect( Position.createFromParentAndOffset( ul, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] ); - expect( Position.createFromParentAndOffset( ul, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] ); + const positionCopy = Position._createAt( position ); - expect( Position.createFromParentAndOffset( li1, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 0 ] ); - expect( Position.createFromParentAndOffset( li1, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] ); - expect( Position.createFromParentAndOffset( li1, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] ); - expect( Position.createFromParentAndOffset( li1, 3 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 3 ] ); - } ); + expect( positionCopy ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); + expect( positionCopy ).to.have.property( 'root' ).that.equals( position.root ); + expect( positionCopy ).to.not.equal( position ); + } ); - it( 'throws when parent is not an element', () => { - expect( () => { - Position.createFromParentAndOffset( b, 0 ); - } ).to.throw( CKEditorError, /^model-position-parent-incorrect/ ); - } ); + it( 'should create positions from LivePosition', () => { + const position = new LivePosition( root, [ 0, 0 ] ); + const created = Position._createAt( position ); - it( 'works with a doc frag', () => { - const frag = new DocumentFragment(); + expect( created.isEqual( position ) ).to.be.true; + expect( created ).to.not.be.equal( position ); + expect( created ).to.be.instanceof( Position ); + expect( created ).to.not.be.instanceof( LivePosition ); + } ); - expect( Position.createFromParentAndOffset( frag, 0 ) ).to.have.property( 'root', frag ); - } ); - } ); + it( 'should create positions from node and offset', () => { + expect( Position._createAt( root, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] ); + expect( Position._createAt( root, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); + expect( Position._createAt( root, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] ); - describe( 'createAt()', () => { - it( 'should throw if no offset is passed', () => { - expect( () => Position.createAt( ul ) ).to.throw( CKEditorError, /model-position-createAt-offset-required/ ); - } ); + expect( Position._createAt( p, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 0, 0 ] ); - it( 'should create positions from positions', () => { - const spy = testUtils.sinon.spy( Position, 'createFromPosition' ); + expect( Position._createAt( ul, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); + expect( Position._createAt( ul, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] ); + expect( Position._createAt( ul, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] ); - expect( Position.createAt( Position.createAt( ul, 0 ) ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); + expect( Position._createAt( li1, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 0 ] ); + expect( Position._createAt( li1, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] ); + expect( Position._createAt( li1, 2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] ); + expect( Position._createAt( li1, 3 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 3 ] ); + } ); - expect( spy.calledOnce ).to.be.true; - } ); + it( 'should create positions from node and flag', () => { + expect( Position._createAt( root, 'end' ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] ); - it( 'should create positions from node and offset', () => { - expect( Position.createAt( ul, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); - expect( Position.createAt( li1, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 0 ] ); - expect( Position.createAt( ul, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] ); - } ); + expect( Position._createAt( p, 'before' ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] ); + expect( Position._createAt( a, 'before' ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] ); - it( 'should create positions from node and flag', () => { - expect( Position.createAt( root, 'end' ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] ); + expect( Position._createAt( p, 'after' ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); + expect( Position._createAt( a, 'after' ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] ); - expect( Position.createAt( p, 'before' ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] ); - expect( Position.createAt( a, 'before' ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] ); + expect( Position._createAt( ul, 'end' ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] ); + } ); - expect( Position.createAt( p, 'after' ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); - expect( Position.createAt( a, 'after' ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] ); + it( 'throws when parent is not an element', () => { + expect( () => { + Position._createAt( b, 0 ); + } ).to.throw( CKEditorError, /^model-position-parent-incorrect/ ); + } ); + + it( 'works with a doc frag', () => { + const frag = new DocumentFragment(); - expect( Position.createAt( ul, 'end' ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] ); + expect( Position._createAt( frag, 0 ) ).to.have.property( 'root', frag ); + } ); } ); - } ); - describe( 'createBefore()', () => { - it( 'should create positions before elements', () => { - expect( Position.createBefore( p ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] ); + describe( '_createBefore()', () => { + it( 'should create positions before elements', () => { + expect( Position._createBefore( p ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] ); - expect( Position.createBefore( ul ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); + expect( Position._createBefore( ul ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); - expect( Position.createBefore( li1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); + expect( Position._createBefore( li1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); - expect( Position.createBefore( f ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 0 ] ); - expect( Position.createBefore( o ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] ); - expect( Position.createBefore( z ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] ); + expect( Position._createBefore( f ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 0 ] ); + expect( Position._createBefore( o ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] ); + expect( Position._createBefore( z ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] ); - expect( Position.createBefore( li2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] ); + expect( Position._createBefore( li2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] ); - expect( Position.createBefore( b ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 0 ] ); - expect( Position.createBefore( a ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] ); - expect( Position.createBefore( r ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] ); - } ); + expect( Position._createBefore( b ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 0 ] ); + expect( Position._createBefore( a ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] ); + expect( Position._createBefore( r ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] ); + } ); - it( 'should throw error if one try to create positions before root', () => { - expect( () => { - Position.createBefore( root ); - } ).to.throw( CKEditorError, /model-position-before-root/ ); + it( 'should throw error if one try to create positions before root', () => { + expect( () => { + Position._createBefore( root ); + } ).to.throw( CKEditorError, /model-position-before-root/ ); + } ); } ); - } ); - describe( 'createAfter()', () => { - it( 'should create positions after elements', () => { - expect( Position.createAfter( p ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); + describe( '_createAfter()', () => { + it( 'should create positions after elements', () => { + expect( Position._createAfter( p ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] ); - expect( Position.createAfter( ul ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] ); + expect( Position._createAfter( ul ) ).to.have.property( 'path' ).that.deep.equals( [ 2 ] ); - expect( Position.createAfter( li1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] ); + expect( Position._createAfter( li1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1 ] ); - expect( Position.createAfter( f ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] ); - expect( Position.createAfter( o ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] ); - expect( Position.createAfter( z ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 3 ] ); + expect( Position._createAfter( f ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 1 ] ); + expect( Position._createAfter( o ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 2 ] ); + expect( Position._createAfter( z ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 0, 3 ] ); - expect( Position.createAfter( li2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] ); - - expect( Position.createAfter( b ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] ); - expect( Position.createAfter( a ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] ); - expect( Position.createAfter( r ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 3 ] ); - } ); - - it( 'should throw error if one try to make positions after root', () => { - expect( () => { - Position.createAfter( root ); - } ).to.throw( CKEditorError, /model-position-after-root/ ); - } ); - } ); + expect( Position._createAfter( li2 ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 2 ] ); - describe( 'createFromPosition()', () => { - it( 'should create a copy of given position', () => { - const original = new Position( root, [ 1, 2, 3 ] ); - const position = Position.createFromPosition( original ); + expect( Position._createAfter( b ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 1 ] ); + expect( Position._createAfter( a ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 2 ] ); + expect( Position._createAfter( r ) ).to.have.property( 'path' ).that.deep.equals( [ 1, 1, 3 ] ); + } ); - expect( position ).to.be.instanceof( Position ); - expect( position.isEqual( original ) ).to.be.true; - expect( position ).not.to.be.equal( original ); + it( 'should throw error if one try to make positions after root', () => { + expect( () => { + Position._createAfter( root ); + } ).to.throw( CKEditorError, /model-position-after-root/ ); + } ); } ); } ); @@ -642,6 +638,18 @@ describe( 'Position', () => { } ); } ); + describe( 'clone()', () => { + it( 'should return new instance of position', () => { + const position = Position._createAt( ul, 0 ); + + const positionCopy = position.clone(); + + expect( positionCopy ).to.have.property( 'path' ).that.deep.equals( [ 1, 0 ] ); + expect( positionCopy ).to.have.property( 'root' ).that.equals( position.root ); + expect( positionCopy ).to.not.equal( position ); + } ); + } ); + // Note: We don't create model element structure in these tests because this method // is used by OT so it must not check the structure. describe( 'getTransformedByOperation()', () => { @@ -653,7 +661,8 @@ describe( 'Position', () => { describe( 'by AttributeOperation', () => { it( 'nothing should change', () => { - const op = new AttributeOperation( Range.createFromParentsAndOffsets( root, 1, root, 6 ), 'key', true, false, 1 ); + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 6 ) ); + const op = new AttributeOperation( range, 'key', true, false, 1 ); const transformed = pos.getTransformedByOperation( op ); expect( transformed.path ).to.deep.equal( [ 3, 2 ] ); @@ -674,7 +683,7 @@ describe( 'Position', () => { describe( 'by MarkerOperation', () => { it( 'nothing should change', () => { const op = new MarkerOperation( - 'marker', null, Range.createFromParentsAndOffsets( root, 1, root, 6 ), model.markers, true, 1 + 'marker', null, new Range( Position._createAt( root, 1 ), Position._createAt( root, 6 ) ), model.markers, true, 1 ); const transformed = pos.getTransformedByOperation( op ); diff --git a/tests/model/range.js b/tests/model/range.js index 87686d599..6fccc7a03 100644 --- a/tests/model/range.js +++ b/tests/model/range.js @@ -68,8 +68,8 @@ describe( 'Range', () => { describe( 'isEqual()', () => { it( 'should return true if the ranges are the same', () => { - const sameStart = Position.createFromPosition( start ); - const sameEnd = Position.createFromPosition( end ); + const sameStart = Position._createAt( start ); + const sameEnd = Position._createAt( end ); const sameRange = new Range( sameStart, sameEnd ); @@ -80,7 +80,7 @@ describe( 'Range', () => { const range = new Range( start, end ); const diffStart = new Position( root, [ 0 ] ); - const sameEnd = Position.createFromPosition( end ); + const sameEnd = Position._createAt( end ); const diffRange = new Range( diffStart, sameEnd ); @@ -108,7 +108,7 @@ describe( 'Range', () => { describe( 'isIntersecting()', () => { it( 'should return true if given range is equal', () => { - const otherRange = Range.createFromRange( range ); + const otherRange = range.clone(); expect( range.isIntersecting( otherRange ) ).to.be.true; } ); @@ -155,59 +155,28 @@ describe( 'Range', () => { root._insertChild( 0, [ p ] ); } ); - describe( 'createIn()', () => { + describe( '_createIn()', () => { it( 'should return range', () => { - const range = Range.createIn( p ); + const range = Range._createIn( p ); expect( range.start.path ).to.deep.equal( [ 0, 0 ] ); expect( range.end.path ).to.deep.equal( [ 0, 3 ] ); } ); } ); - describe( 'createOn()', () => { + describe( '_createOn()', () => { it( 'should return range', () => { - const range = Range.createOn( p ); + const range = Range._createOn( p ); expect( range.start.path ).to.deep.equal( [ 0 ] ); expect( range.end.path ).to.deep.equal( [ 1 ] ); } ); } ); - describe( 'createCollapsedAt()', () => { - it( 'should return new collapsed range at the given item position', () => { - const item = new Element( 'p', null, new Text( 'foo' ) ); - const range = Range.createCollapsedAt( item, 0 ); - - expect( range.start.parent ).to.equal( item ); - expect( range.start.offset ).to.equal( 0 ); - - expect( range.isCollapsed ).to.be.true; - } ); - - it( 'should return new collapse range at the given item position and offset', () => { - const item = new Element( 'p', null, new Text( 'foo' ) ); - const range = Range.createCollapsedAt( item, 1 ); - - expect( range.start.parent ).to.equal( item ); - expect( range.start.offset ).to.equal( 1 ); - - expect( range.isCollapsed ).to.be.true; - } ); - } ); - - describe( 'createFromParentsAndOffsets()', () => { - it( 'should return range', () => { - const range = Range.createFromParentsAndOffsets( root, 0, p, 2 ); - - expect( range.start.path ).to.deep.equal( [ 0 ] ); - expect( range.end.path ).to.deep.equal( [ 0, 2 ] ); - } ); - } ); - - describe( 'createFromPositionAndShift()', () => { + describe( '_createFromPositionAndShift()', () => { it( 'should make range from start position and offset', () => { const position = new Position( root, [ 1, 2, 3 ] ); - const range = Range.createFromPositionAndShift( position, 4 ); + const range = Range._createFromPositionAndShift( position, 4 ); expect( range ).to.be.instanceof( Range ); expect( range.start.isEqual( position ) ).to.be.true; @@ -216,21 +185,21 @@ describe( 'Range', () => { } ); } ); - describe( 'createFromRange()', () => { + describe( 'clone()', () => { it( 'should create a new instance of Range that is equal to passed range', () => { - const clone = Range.createFromRange( range ); + const clone = range.clone(); expect( clone ).not.to.be.equal( range ); // clone is not pointing to the same object as position expect( clone.isEqual( range ) ).to.be.true; // but they are equal in the position-sense } ); } ); - describe( 'createFromRanges()', () => { + describe( '_createFromRanges()', () => { function makeRanges( root, ...points ) { const ranges = []; for ( let i = 0; i < points.length; i += 2 ) { - ranges.push( Range.createFromParentsAndOffsets( root, points[ i ], root, points[ i + 1 ] ) ); + ranges.push( new Range( Position._createAt( root, points[ i ] ), Position._createAt( root, points[ i + 1 ] ) ) ); } return ranges; @@ -242,20 +211,20 @@ describe( 'Range', () => { it( 'should throw if empty array is passed', () => { expect( () => { - Range.createFromRanges( [] ); + Range._createFromRanges( [] ); } ).to.throw( CKEditorError, /^range-create-from-ranges-empty-array/ ); } ); it( 'should return a copy of the range if only one range was passed', () => { - const original = Range.createFromParentsAndOffsets( root, 2, root, 3 ); - const range = Range.createFromRanges( [ original ] ); + const original = new Range( Position._createAt( root, 2 ), Position._createAt( root, 3 ) ); + const range = Range._createFromRanges( [ original ] ); expect( range.isEqual( original ) ).to.be.true; expect( range ).not.to.be.equal( original ); } ); it( 'should combine ranges with reference range', () => { - const range = Range.createFromRanges( makeRanges( root, 3, 7, 2, 3, 7, 9, 11, 14, 0, 1 ) ); + const range = Range._createFromRanges( makeRanges( root, 3, 7, 2, 3, 7, 9, 11, 14, 0, 1 ) ); expect( range.start.offset ).to.equal( 2 ); expect( range.end.offset ).to.equal( 9 ); @@ -417,7 +386,7 @@ describe( 'Range', () => { } ); it( 'should return true if ranges are equal and check is not strict', () => { - const otherRange = Range.createFromRange( range ); + const otherRange = range.clone(); expect( range.containsRange( otherRange, true ) ).to.be.true; } ); @@ -460,7 +429,7 @@ describe( 'Range', () => { } ); it( 'should return true if element is inside range and false when it is not inside range', () => { - const range = Range.createFromParentsAndOffsets( root, 1, root, 3 ); // Range over `b` and `c`. + const range = new Range( Position._createAt( root, 1 ), Position._createAt( root, 3 ) ); // Range over `b` and `c`. expect( range.containsItem( a ) ).to.be.false; expect( range.containsItem( b ) ).to.be.true; @@ -791,7 +760,7 @@ describe( 'Range', () => { } ); it( 'should return a range equal to both ranges if both ranges are equal', () => { - const otherRange = Range.createFromRange( range ); + const otherRange = range.clone(); const common = range.getIntersection( otherRange ); expect( common.isEqual( range ) ).to.be.true; @@ -804,7 +773,7 @@ describe( 'Range', () => { let gyPos; beforeEach( () => { - range = Range.createFromParentsAndOffsets( root, 2, root, 5 ); + range = new Range( Position._createAt( root, 2 ), Position._createAt( root, 5 ) ); gyPos = new Position( gy, [ 0 ] ); } ); @@ -815,7 +784,8 @@ describe( 'Range', () => { describe( 'by AttributeOperation', () => { it( 'nothing should change', () => { - const op = new AttributeOperation( Range.createFromParentsAndOffsets( root, 1, root, 6 ), 'key', true, false, 1 ); + const opRange = new Range( Position._createAt( root, 1 ), Position._createAt( root, 6 ) ); + const op = new AttributeOperation( opRange, 'key', true, false, 1 ); const transformed = range.getTransformedByOperation( op ); expectRange( transformed[ 0 ], 2, 5 ); @@ -848,7 +818,7 @@ describe( 'Range', () => { describe( 'by MarkerOperation', () => { it( 'nothing should change', () => { const op = new MarkerOperation( - 'marker', null, Range.createFromParentsAndOffsets( root, 1, root, 6 ), model.markers, true, 1 + 'marker', null, new Range( Position._createAt( root, 1 ), Position._createAt( root, 6 ) ), model.markers, true, 1 ); const transformed = range.getTransformedByOperation( op ); @@ -1215,7 +1185,7 @@ describe( 'Range', () => { describe( 'getTransformedByOperations()', () => { beforeEach( () => { root._appendChild( new Text( 'foobar' ) ); - range = Range.createFromParentsAndOffsets( root, 2, root, 5 ); + range = new Range( Position._createAt( root, 2 ), Position._createAt( root, 5 ) ); } ); function expectRange( range, startOffset, endOffset ) { diff --git a/tests/model/schema.js b/tests/model/schema.js index 826ae96d8..5a3ceb8ae 100644 --- a/tests/model/schema.js +++ b/tests/model/schema.js @@ -15,7 +15,6 @@ import Text from '../../src/model/text'; import TextProxy from '../../src/model/textproxy'; import Position from '../../src/model/position'; import Range from '../../src/model/range'; -import Selection from '../../src/model/selection'; import { getData, setData, stringify, parse } from '../../src/dev-utils/model'; @@ -394,8 +393,8 @@ describe( 'Schema', () => { } ); it( 'accepts a schemaContext instance as a context', () => { - const rootContext = new SchemaContext( Position.createAt( root1, 0 ) ); - const paragraphContext = new SchemaContext( Position.createAt( r1p1, 0 ) ); + const rootContext = new SchemaContext( Position._createAt( root1, 0 ) ); + const paragraphContext = new SchemaContext( Position._createAt( r1p1, 0 ) ); expect( schema.checkChild( rootContext, 'paragraph' ) ).to.be.true; expect( schema.checkChild( rootContext, '$text' ) ).to.be.false; @@ -405,8 +404,8 @@ describe( 'Schema', () => { } ); it( 'accepts a position as a context', () => { - const posInRoot = Position.createAt( root1, 0 ); - const posInParagraph = Position.createAt( r1p1, 0 ); + const posInRoot = Position._createAt( root1, 0 ); + const posInParagraph = Position._createAt( r1p1, 0 ); expect( schema.checkChild( posInRoot, 'paragraph' ) ).to.be.true; expect( schema.checkChild( posInRoot, '$text' ) ).to.be.false; @@ -486,16 +485,16 @@ describe( 'Schema', () => { } ); it( 'accepts a position as a context', () => { - const posInRoot = Position.createAt( root1, 0 ); - const posInParagraph = Position.createAt( r1p1, 0 ); + const posInRoot = Position._createAt( root1, 0 ); + const posInParagraph = Position._createAt( r1p1, 0 ); expect( schema.checkAttribute( posInRoot, 'align' ) ).to.be.false; expect( schema.checkAttribute( posInParagraph, 'align' ) ).to.be.true; } ); it( 'accepts a schemaContext instance as a context', () => { - const rootContext = new SchemaContext( Position.createAt( root1, 0 ) ); - const paragraphContext = new SchemaContext( Position.createAt( r1p1, 0 ) ); + const rootContext = new SchemaContext( Position._createAt( root1, 0 ) ); + const paragraphContext = new SchemaContext( Position._createAt( r1p1, 0 ) ); expect( schema.checkAttribute( rootContext, 'align' ) ).to.be.false; expect( schema.checkAttribute( paragraphContext, 'align' ) ).to.be.true; @@ -743,7 +742,7 @@ describe( 'Schema', () => { new Element( '$root', null, [ listItem, listItemToMerge ] ); - const position = Position.createAfter( listItem ); + const position = Position._createAfter( listItem ); expect( schema.checkMerge( position ) ).to.be.true; } ); @@ -758,7 +757,7 @@ describe( 'Schema', () => { listItem ] ); - const position = Position.createBefore( listItem ); + const position = Position._createBefore( listItem ); expect( () => { expect( schema.checkMerge( position ) ); @@ -776,7 +775,7 @@ describe( 'Schema', () => { listItem ] ); - const position = Position.createBefore( listItem ); + const position = Position._createBefore( listItem ); expect( () => { expect( schema.checkMerge( position ) ); @@ -793,7 +792,7 @@ describe( 'Schema', () => { listItem ] ); - const position = Position.createAfter( listItem ); + const position = Position._createAfter( listItem ); expect( () => { expect( schema.checkMerge( position ) ); @@ -811,7 +810,7 @@ describe( 'Schema', () => { new Text( 'bar' ) ] ); - const position = Position.createBefore( listItem ); + const position = Position._createBefore( listItem ); expect( () => { expect( schema.checkMerge( position ) ); @@ -1187,7 +1186,7 @@ describe( 'Schema', () => { setData( model, input ); const validRanges = schema.getValidRanges( doc.selection.getRanges(), attribute ); - const sel = new Selection( validRanges ); + const sel = model.createSelection( validRanges ); expect( stringify( root, sel ) ).to.equal( output ); } @@ -1575,7 +1574,7 @@ describe( 'Schema', () => { it( 'should return position ancestor that allows to insert given node to it', () => { const node = new Element( 'paragraph' ); - const allowedParent = schema.findAllowedParent( node, Position.createAt( r1bQp, 0 ) ); + const allowedParent = schema.findAllowedParent( node, Position._createAt( r1bQp, 0 ) ); expect( allowedParent ).to.equal( r1bQ ); } ); @@ -1583,7 +1582,7 @@ describe( 'Schema', () => { it( 'should return position ancestor that allows to insert given node to it when position is already i such an element', () => { const node = new Text( 'text' ); - const parent = schema.findAllowedParent( node, Position.createAt( r1bQp, 0 ) ); + const parent = schema.findAllowedParent( node, Position._createAt( r1bQp, 0 ) ); expect( parent ).to.equal( r1bQp ); } ); @@ -1597,7 +1596,7 @@ describe( 'Schema', () => { } ); const node = new Element( 'div' ); - const parent = schema.findAllowedParent( node, Position.createAt( r1bQp, 0 ) ); + const parent = schema.findAllowedParent( node, Position._createAt( r1bQp, 0 ) ); expect( parent ).to.null; } ); @@ -1611,7 +1610,7 @@ describe( 'Schema', () => { } ); const node = new Element( 'div' ); - const parent = schema.findAllowedParent( node, Position.createAt( r1bQp, 0 ) ); + const parent = schema.findAllowedParent( node, Position._createAt( r1bQp, 0 ) ); expect( parent ).to.null; } ); @@ -1619,7 +1618,7 @@ describe( 'Schema', () => { it( 'should return null when there is no allowed ancestor for given position', () => { const node = new Element( 'section' ); - const parent = schema.findAllowedParent( node, Position.createAt( r1bQp, 0 ) ); + const parent = schema.findAllowedParent( node, Position._createAt( r1bQp, 0 ) ); expect( parent ).to.null; } ); @@ -2763,6 +2762,14 @@ describe( 'Schema', () => { expect( schema.isObject( 'caption' ) ).to.be.false; } ); } ); + + describe( 'createContext()', () => { + it( 'should return SchemaContext instance', () => { + const ctx = schema.createContext( [ 'a', 'b', 'c' ] ); + + expect( ctx ).to.be.instanceof( SchemaContext ); + } ); + } ); } ); describe( 'SchemaContext', () => { @@ -2866,7 +2873,7 @@ describe( 'SchemaContext', () => { } ); it( 'creates context based on a position', () => { - const pos = Position.createAt( root.getChild( 0 ).getChild( 0 ), 0 ); + const pos = Position._createAt( root.getChild( 0 ).getChild( 0 ), 0 ); const ctx = new SchemaContext( pos ); expect( ctx.length ).to.equal( 3 ); diff --git a/tests/model/selection.js b/tests/model/selection.js index 630420c5c..19f09a870 100644 --- a/tests/model/selection.js +++ b/tests/model/selection.js @@ -181,7 +181,7 @@ describe( 'Selection', () => { } ); it( 'is false when last range is collapsed', () => { - const pos = Position.createAt( root, 0 ); + const pos = Position._createAt( root, 0 ); selection.setTo( pos ); @@ -193,9 +193,9 @@ describe( 'Selection', () => { let r1, r2, r3; beforeEach( () => { - r1 = Range.createFromParentsAndOffsets( root, 2, root, 4 ); - r2 = Range.createFromParentsAndOffsets( root, 4, root, 6 ); - r3 = Range.createFromParentsAndOffsets( root, 1, root, 2 ); + r1 = new Range( Position._createAt( root, 2 ), Position._createAt( root, 4 ) ); + r2 = new Range( Position._createAt( root, 4 ), Position._createAt( root, 6 ) ); + r3 = new Range( Position._createAt( root, 1 ), Position._createAt( root, 2 ) ); selection.setTo( [ r1, r2 ] ); } ); @@ -398,7 +398,7 @@ describe( 'Selection', () => { } ); it( 'should set selection at the specified position', () => { - const pos = Position.createFromParentAndOffset( root, 3 ); + const pos = Position._createAt( root, 3 ); selection.setTo( pos ); @@ -430,13 +430,13 @@ describe( 'Selection', () => { const spy = sinon.spy(); selection.on( 'change:range', spy ); - selection.setFocus( Position.createAt( root, 'end' ) ); + selection.setFocus( Position._createAt( root, 'end' ) ); expect( spy.calledOnce ).to.be.true; } ); it( 'throws if there are no ranges in selection', () => { - const endPos = Position.createAt( root, 'end' ); + const endPos = Position._createAt( root, 'end' ); expect( () => { selection.setFocus( endPos ); @@ -444,8 +444,8 @@ describe( 'Selection', () => { } ); it( 'modifies existing collapsed selection', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 2 ); selection.setTo( startPos ); @@ -456,8 +456,8 @@ describe( 'Selection', () => { } ); it( 'makes existing collapsed selection a backward selection', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 0 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 0 ); selection.setTo( startPos ); @@ -469,9 +469,9 @@ describe( 'Selection', () => { } ); it( 'modifies existing non-collapsed selection', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); - const newEndPos = Position.createAt( root, 3 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 2 ); + const newEndPos = Position._createAt( root, 3 ); selection.setTo( new Range( startPos, endPos ) ); @@ -482,9 +482,9 @@ describe( 'Selection', () => { } ); it( 'makes existing non-collapsed selection a backward selection', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); - const newEndPos = Position.createAt( root, 0 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 2 ); + const newEndPos = Position._createAt( root, 0 ); selection.setTo( new Range( startPos, endPos ) ); @@ -496,9 +496,9 @@ describe( 'Selection', () => { } ); it( 'makes existing backward selection a forward selection', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); - const newEndPos = Position.createAt( root, 3 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 2 ); + const newEndPos = Position._createAt( root, 3 ); selection.setTo( new Range( startPos, endPos ), { backward: true } ); @@ -510,9 +510,9 @@ describe( 'Selection', () => { } ); it( 'modifies existing backward selection', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); - const newEndPos = Position.createAt( root, 0 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 2 ); + const newEndPos = Position._createAt( root, 0 ); selection.setTo( new Range( startPos, endPos ), { backward: true } ); @@ -525,12 +525,12 @@ describe( 'Selection', () => { it( 'modifies only the last range', () => { // Offsets are chosen in this way that the order of adding ranges must count, not their document order. - const startPos1 = Position.createAt( root, 4 ); - const endPos1 = Position.createAt( root, 5 ); - const startPos2 = Position.createAt( root, 1 ); - const endPos2 = Position.createAt( root, 2 ); + const startPos1 = Position._createAt( root, 4 ); + const endPos1 = Position._createAt( root, 5 ); + const startPos2 = Position._createAt( root, 1 ); + const endPos2 = Position._createAt( root, 2 ); - const newEndPos = Position.createAt( root, 0 ); + const newEndPos = Position._createAt( root, 0 ); selection.setTo( [ new Range( startPos1, endPos1 ), @@ -557,8 +557,8 @@ describe( 'Selection', () => { } ); it( 'collapses the selection when extending to the anchor', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); + const startPos = Position._createAt( root, 1 ); + const endPos = Position._createAt( root, 2 ); selection.setTo( new Range( startPos, endPos ) ); @@ -567,20 +567,6 @@ describe( 'Selection', () => { expect( selection.focus.compareWith( startPos ) ).to.equal( 'same' ); expect( selection.isCollapsed ).to.be.true; } ); - - it( 'uses Position.createAt', () => { - const startPos = Position.createAt( root, 1 ); - const endPos = Position.createAt( root, 2 ); - const newEndPos = Position.createAt( root, 4 ); - const spy = testUtils.sinon.stub( Position, 'createAt' ).returns( newEndPos ); - - selection.setTo( new Range( startPos, endPos ) ); - - selection.setFocus( root, 'end' ); - - expect( spy.calledOnce ).to.be.true; - expect( selection.focus.compareWith( newEndPos ) ).to.equal( 'same' ); - } ); } ); describe( 'setTo - selection set to null', () => { diff --git a/tests/model/treewalker.js b/tests/model/treewalker.js index 4dc7d2822..b96be6045 100644 --- a/tests/model/treewalker.js +++ b/tests/model/treewalker.js @@ -568,7 +568,7 @@ describe( 'TreeWalker', () => { describe( 'forward treewalker', () => { it( 'should jump over all text nodes', () => { const walker = new TreeWalker( { - startPosition: Position.createFromParentAndOffset( paragraph, 0 ) + startPosition: Position._createAt( paragraph, 0 ) } ); walker.skip( value => value.type == 'text' ); @@ -579,7 +579,7 @@ describe( 'TreeWalker', () => { it( 'should do not move if the condition is false', () => { const walker = new TreeWalker( { - startPosition: Position.createFromParentAndOffset( paragraph, 1 ) + startPosition: Position._createAt( paragraph, 1 ) } ); walker.skip( () => false ); @@ -590,7 +590,7 @@ describe( 'TreeWalker', () => { it( 'should move to the end if the condition is true', () => { const walker = new TreeWalker( { - startPosition: Position.createFromParentAndOffset( paragraph, 1 ) + startPosition: Position._createAt( paragraph, 1 ) } ); walker.skip( () => true ); @@ -603,7 +603,7 @@ describe( 'TreeWalker', () => { describe( 'backward treewalker', () => { it( 'should jump over all text nodes', () => { const walker = new TreeWalker( { - startPosition: Position.createFromParentAndOffset( paragraph, 3 ), + startPosition: Position._createAt( paragraph, 3 ), direction: 'backward' } ); @@ -615,7 +615,7 @@ describe( 'TreeWalker', () => { it( 'should do not move if the condition is false', () => { const walker = new TreeWalker( { - startPosition: Position.createFromParentAndOffset( paragraph, 1 ), + startPosition: Position._createAt( paragraph, 1 ), direction: 'backward' } ); @@ -627,7 +627,7 @@ describe( 'TreeWalker', () => { it( 'should move to the end if the condition is true', () => { const walker = new TreeWalker( { - startPosition: Position.createFromParentAndOffset( paragraph, 1 ), + startPosition: Position._createAt( paragraph, 1 ), direction: 'backward' } ); @@ -660,11 +660,11 @@ function expectText( value, expected, options = {} ) { expect( value.length ).to.equal( value.item.data.length ); if ( options.direction == 'backward' ) { - previousPosition = Position.createAfter( value.item ); - nextPosition = Position.createBefore( value.item ); + previousPosition = Position._createAfter( value.item ); + nextPosition = Position._createBefore( value.item ); } else { - previousPosition = Position.createBefore( value.item ); - nextPosition = Position.createAfter( value.item ); + previousPosition = Position._createBefore( value.item ); + nextPosition = Position._createAfter( value.item ); } expect( value.previousPosition ).to.deep.equal( previousPosition ); @@ -678,11 +678,11 @@ function expectStart( value, expected, options = {} ) { expect( value.length ).to.equal( 1 ); if ( options.direction == 'backward' ) { - previousPosition = Position.createAfter( value.item ); - nextPosition = Position.createBefore( value.item ); + previousPosition = Position._createAfter( value.item ); + nextPosition = Position._createBefore( value.item ); } else { - previousPosition = Position.createBefore( value.item ); - nextPosition = Position.createFromParentAndOffset( value.item, 0 ); + previousPosition = Position._createBefore( value.item ); + nextPosition = Position._createAt( value.item, 0 ); } if ( options.shallow ) { @@ -699,11 +699,11 @@ function expectEnd( value, expected, options = {} ) { expect( value.length ).to.be.undefined; if ( options.direction == 'backward' ) { - previousPosition = Position.createAfter( value.item ); - nextPosition = Position.createFromParentAndOffset( value.item, value.item.maxOffset ); + previousPosition = Position._createAfter( value.item ); + nextPosition = Position._createAt( value.item, value.item.maxOffset ); } else { - previousPosition = Position.createFromParentAndOffset( value.item, value.item.maxOffset ); - nextPosition = Position.createAfter( value.item ); + previousPosition = Position._createAt( value.item, value.item.maxOffset ); + nextPosition = Position._createAfter( value.item ); } expect( value.previousPosition ).to.deep.equal( previousPosition ); diff --git a/tests/model/utils-tests/utils.js b/tests/model/utils-tests/utils.js index 89a7a2d74..d5dc37868 100644 --- a/tests/model/utils-tests/utils.js +++ b/tests/model/utils-tests/utils.js @@ -32,7 +32,7 @@ describe( 'getNodesAndText', () => { } ); it( 'reads two elements with text', () => { - expect( getNodesAndText( Range.createIn( root ) ) ).to.equal( 'DIVfoobarDIVPabcxyzP' ); + expect( getNodesAndText( Range._createIn( root ) ) ).to.equal( 'DIVfoobarDIVPabcxyzP' ); } ); } ); diff --git a/tests/model/utils/insertcontent.js b/tests/model/utils/insertcontent.js index 0a490cbbc..312512621 100644 --- a/tests/model/utils/insertcontent.js +++ b/tests/model/utils/insertcontent.js @@ -8,7 +8,6 @@ import insertContent from '../../../src/model/utils/insertcontent'; import DocumentFragment from '../../../src/model/documentfragment'; import Text from '../../../src/model/text'; import Element from '../../../src/model/element'; -import Selection from '../../../src/model/selection'; import Position from '../../../src/model/position'; import { setData, getData, parse } from '../../../src/dev-utils/model'; @@ -38,7 +37,7 @@ describe( 'DataController utils', () => { model.schema.extend( '$text', { allowIn: '$root' } ); setData( model, 'a[]bc' ); - const selection = new Selection( new Position( doc.getRoot(), [ 2 ] ) ); + const selection = model.createSelection( model.createPositionFromPath( doc.getRoot(), [ 2 ] ) ); model.change( writer => { insertContent( model, writer.createText( 'x' ), selection ); @@ -50,8 +49,8 @@ describe( 'DataController utils', () => { model.schema.extend( '$text', { allowIn: '$root' } ); setData( model, 'a[]bc' ); - const selection = new Selection( new Position( doc.getRoot(), [ 2 ] ) ); - const selectionCopy = new Selection( new Position( doc.getRoot(), [ 2 ] ) ); + const selection = model.createSelection( model.createPositionFromPath( doc.getRoot(), [ 2 ] ) ); + const selectionCopy = model.createSelection( model.createPositionFromPath( doc.getRoot(), [ 2 ] ) ); expect( selection.isEqual( selectionCopy ) ).to.be.true; @@ -61,7 +60,7 @@ describe( 'DataController utils', () => { expect( selection.isEqual( selectionCopy ) ).to.be.false; - const insertionSelection = new Selection( new Position( doc.getRoot(), [ 3 ] ) ); + const insertionSelection = model.createSelection( model.createPositionFromPath( doc.getRoot(), [ 3 ] ) ); expect( selection.isEqual( insertionSelection ) ).to.be.true; } ); diff --git a/tests/model/utils/modifyselection.js b/tests/model/utils/modifyselection.js index 41fc5ef5e..645f088ee 100644 --- a/tests/model/utils/modifyselection.js +++ b/tests/model/utils/modifyselection.js @@ -4,7 +4,6 @@ */ import Model from '../../../src/model/model'; -import Selection from '../../../src/model/selection'; import modifySelection from '../../../src/model/utils/modifyselection'; import { setData, stringify } from '../../../src/dev-utils/model'; @@ -381,7 +380,7 @@ describe( 'DataController utils', () => { // Creating new instance of selection instead of operation on module:engine/model/document~Document#selection. // Document's selection will throw errors in some test cases (which are correct cases, but only for // non-document selections). - const testSelection = new Selection( doc.selection ); + const testSelection = model.createSelection( doc.selection ); modifySelection( model, testSelection, { unit: 'codePoint', direction: 'backward' } ); expect( stringify( doc.getRoot(), testSelection ) ).to.equal( '

foob[̂]ar

' ); @@ -987,7 +986,7 @@ describe( 'DataController utils', () => { // Creating new instance of selection instead of operation on module:engine/model/document~Document#selection. // Document's selection will throw errors in some test cases (which are correct cases, but only for // non-document selections). - const testSelection = new Selection( doc.selection ); + const testSelection = model.createSelection( doc.selection ); modifySelection( model, testSelection, options ); expect( stringify( doc.getRoot(), testSelection ) ).to.equal( output ); diff --git a/tests/model/utils/selection-post-fixer.js b/tests/model/utils/selection-post-fixer.js index d13f7126b..60e25898a 100644 --- a/tests/model/utils/selection-post-fixer.js +++ b/tests/model/utils/selection-post-fixer.js @@ -4,8 +4,6 @@ */ import Model from '../../../src/model/model'; -import ModelPosition from '../../../src/model/position'; -import ModelRange from '../../../src/model/range'; import { injectSelectionPostFixer } from '../../../src/model/utils/selection-post-fixer'; @@ -88,7 +86,7 @@ describe( 'Selection post-fixer', () => { // foo[] model.change( writer => { writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 1 ) + writer.createRange( writer.createPositionAt( modelRoot, 1 ), writer.createPositionAt( modelRoot, 1 ) ) ); } ); @@ -109,9 +107,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #1', () => { // f[oo]... model.change( writer => { - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 0 ), 1, - modelRoot.getChild( 1 ).getChild( 0 ), 1 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 1 ).getChild( 0 ), 1 ) ) ); } ); @@ -127,9 +125,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #2', () => { // ...
[
b]ar model.change( writer => { - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 1 ).getChild( 0 ), 1, - modelRoot.getChild( 2 ), 1 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 1 ).getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 2 ), 1 ) ) ); } ); @@ -145,9 +143,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #3', () => { // f[oo]... model.change( writer => { - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 0 ), 1, - modelRoot.getChild( 1 ), 0 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 1 ), 0 ) ) ); } ); @@ -163,9 +161,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #4', () => { // foo
a[aab]bb model.change( writer => { - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 1 ).getChild( 0 ).getChild( 0 ), 1, - modelRoot.getChild( 1 ).getChild( 0 ).getChild( 1 ), 2 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 1 ).getChild( 0 ).getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 1 ).getChild( 0 ).getChild( 1 ), 2 ) ) ); } ); @@ -295,8 +293,14 @@ describe( 'Selection post-fixer', () => { it( 'should fix multiple ranges #1', () => { model.change( writer => { const ranges = [ - new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 1, 0 ] ) ), - new ModelRange( new ModelPosition( modelRoot, [ 1, 0, 0, 0 ] ), new ModelPosition( modelRoot, [ 1, 1 ] ) ) + writer.createRange( + writer.createPositionFromPath( modelRoot, [ 0, 1 ] ), + writer.createPositionFromPath( modelRoot, [ 1, 0 ] ) + ), + writer.createRange( + writer.createPositionFromPath( modelRoot, [ 1, 0, 0, 0 ] ), + writer.createPositionFromPath( modelRoot, [ 1, 1 ] ) + ) ]; writer.setSelection( ranges ); } ); @@ -313,8 +317,14 @@ describe( 'Selection post-fixer', () => { it( 'should fix multiple ranges #2', () => { model.change( writer => { const ranges = [ - new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 1, 0 ] ) ), - new ModelRange( new ModelPosition( modelRoot, [ 1, 0, 0, 0 ] ), new ModelPosition( modelRoot, [ 2, 2 ] ) ) + writer.createRange( + writer.createPositionFromPath( modelRoot, [ 0, 1 ] ), + writer.createPositionFromPath( modelRoot, [ 1, 0 ] ) + ), + writer.createRange( + writer.createPositionFromPath( modelRoot, [ 1, 0, 0, 0 ] ), + writer.createPositionFromPath( modelRoot, [ 2, 2 ] ) + ) ]; writer.setSelection( ranges ); @@ -356,9 +366,18 @@ describe( 'Selection post-fixer', () => { it( 'should fix multiple ranges #4', () => { model.change( writer => { const ranges = [ - new ModelRange( new ModelPosition( modelRoot, [ 0, 1 ] ), new ModelPosition( modelRoot, [ 1, 0 ] ) ), - new ModelRange( new ModelPosition( modelRoot, [ 1, 0, 0, 0 ] ), new ModelPosition( modelRoot, [ 2, 1 ] ) ), - new ModelRange( new ModelPosition( modelRoot, [ 2, 2 ] ), new ModelPosition( modelRoot, [ 2, 3 ] ) ) + writer.createRange( + writer.createPositionFromPath( modelRoot, [ 0, 1 ] ), + writer.createPositionFromPath( modelRoot, [ 1, 0 ] ) + ), + writer.createRange( + writer.createPositionFromPath( modelRoot, [ 1, 0, 0, 0 ] ), + writer.createPositionFromPath( modelRoot, [ 2, 1 ] ) + ), + writer.createRange( + writer.createPositionFromPath( modelRoot, [ 2, 2 ] ), + writer.createPositionFromPath( modelRoot, [ 2, 3 ] ) + ) ]; writer.setSelection( ranges ); @@ -388,9 +407,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #1 (crossing object and limit boundaries)', () => { model.change( writer => { // f[oo... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 0 ), 1, - modelRoot.getChild( 1 ).getChild( 0 ), 1 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 1 ).getChild( 0 ), 1 ) ) ); } ); @@ -406,9 +425,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #2 (crossing object boundary)', () => { model.change( writer => { // f[oo]... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 0 ), 1, - modelRoot.getChild( 1 ), 0 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 1 ), 0 ) ) ); } ); @@ -424,9 +443,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #3 (crossing object boundary)', () => { model.change( writer => { // f[oo]... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 0 ), 1, - modelRoot.getChild( 1 ), 1 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 0 ), 1 ), + writer.createPositionAt( modelRoot.getChild( 1 ), 1 ) ) ); } ); @@ -442,9 +461,9 @@ describe( 'Selection post-fixer', () => { it( 'should fix #4 (element selection of not an object)', () => { model.change( writer => { // foo[]... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot.getChild( 1 ), 0, - modelRoot.getChild( 1 ), 1 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot.getChild( 1 ), 0 ), + writer.createPositionAt( modelRoot.getChild( 1 ), 1 ) ) ); } ); @@ -460,9 +479,9 @@ describe( 'Selection post-fixer', () => { it( 'should not fix #1 (element selection of an object)', () => { model.change( writer => { // foo[]... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - modelRoot, 1, - modelRoot, 2 + writer.setSelection( writer.createRange( + writer.createPositionAt( modelRoot, 1 ), + writer.createPositionAt( modelRoot, 2 ) ) ); } ); @@ -480,9 +499,9 @@ describe( 'Selection post-fixer', () => { const caption = modelRoot.getChild( 1 ).getChild( 0 ); // foo... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - caption, 0, - caption, 3 + writer.setSelection( writer.createRange( + writer.createPositionAt( caption, 0 ), + writer.createPositionAt( caption, 3 ) ) ); } ); @@ -500,9 +519,9 @@ describe( 'Selection post-fixer', () => { const caption = modelRoot.getChild( 1 ).getChild( 0 ); // foo... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - caption, 0, - caption, 2 + writer.setSelection( writer.createRange( + writer.createPositionAt( caption, 0 ), + writer.createPositionAt( caption, 2 ) ) ); } ); @@ -520,9 +539,9 @@ describe( 'Selection post-fixer', () => { const caption = modelRoot.getChild( 1 ).getChild( 0 ); // foo... - writer.setSelection( ModelRange.createFromParentsAndOffsets( - caption, 1, - caption, 3 + writer.setSelection( writer.createRange( + writer.createPositionAt( caption, 1 ), + writer.createPositionAt( caption, 3 ) ) ); } ); @@ -713,7 +732,7 @@ describe( 'Selection post-fixer', () => { //
x]xxxxxxxxxxxxxx[xxx][xx]xx[xx]
[]... model.change( writer => { writer.setSelection( - ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 1 ), 0, modelRoot.getChild( 1 ), 0 ) + writer.createRange( writer.createPositionAt( modelRoot.getChild( 1 ), 0 ) ) ); } ); @@ -732,7 +751,7 @@ describe( 'Selection post-fixer', () => { const row = modelRoot.getChild( 1 ).getChild( 0 ); writer.setSelection( - ModelRange.createFromParentsAndOffsets( row, 0, row, 0 ) + writer.createRange( writer.createPositionAt( row, 0 ) ) ); } ); @@ -750,8 +769,8 @@ describe( 'Selection post-fixer', () => { model.change( writer => { writer.setSelection( [ - ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 0 ), - ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 1 ) + writer.createRange( writer.createPositionAt( modelRoot, 0 ) ), + writer.createRange( writer.createPositionAt( modelRoot, 1 ) ) ] ); } ); diff --git a/tests/model/writer.js b/tests/model/writer.js index c2b400a37..fb90ce884 100644 --- a/tests/model/writer.js +++ b/tests/model/writer.js @@ -925,8 +925,8 @@ describe( 'Writer', () => { function getRange( startIndex, endIndex ) { return new Range( - Position.createFromParentAndOffset( root, startIndex ), - Position.createFromParentAndOffset( root, endIndex ) + Position._createAt( root, startIndex ), + Position._createAt( root, endIndex ) ); } @@ -944,7 +944,7 @@ describe( 'Writer', () => { function getCompressedAttrs() { // default: 111---111222---1112------ - const range = Range.createIn( root ); + const range = Range._createIn( root ); return Array.from( range.getItems( { singleCharacters: true } ) ) .map( item => item.getAttribute( 'a' ) || '-' ) @@ -1218,7 +1218,7 @@ describe( 'Writer', () => { appendElement( 'e', { a: 1 }, root ); appendText( 'xxx', root ); - const range = Range.createIn( root ); + const range = Range._createIn( root ); clearAttributes( range ); @@ -1286,7 +1286,7 @@ describe( 'Writer', () => { } ); it( 'should set attributes one by one on range', () => { - const range = Range.createIn( frag ); + const range = Range._createIn( frag ); let spy; model.change( writer => { @@ -1308,7 +1308,7 @@ describe( 'Writer', () => { } ); it( 'should set attributes one by one on range for map as attributes list', () => { - const range = Range.createIn( frag ); + const range = Range._createIn( frag ); let spy; model.change( writer => { @@ -1454,8 +1454,8 @@ describe( 'Writer', () => { it( 'should move flat range of nodes', () => { move( range, new Position( root, [ 1, 3 ] ) ); - expect( getNodesAndText( Range.createIn( root.getChild( 0 ) ) ) ).to.equal( 'PggggPfoPhhhhP' ); - expect( getNodesAndText( Range.createIn( root.getChild( 1 ) ) ) ).to.equal( 'abcobarxyz' ); + expect( getNodesAndText( Range._createIn( root.getChild( 0 ) ) ) ).to.equal( 'PggggPfoPhhhhP' ); + expect( getNodesAndText( Range._createIn( root.getChild( 1 ) ) ) ).to.equal( 'abcobarxyz' ); } ); it( 'should throw if object to move is not a range', () => { @@ -1525,20 +1525,20 @@ describe( 'Writer', () => { expect( root.maxOffset ).to.equal( 1 ); expect( root.childCount ).to.equal( 1 ); - expect( getNodesAndText( Range.createIn( root.getChild( 0 ) ) ) ).to.equal( 'abcxyz' ); + expect( getNodesAndText( Range._createIn( root.getChild( 0 ) ) ) ).to.equal( 'abcxyz' ); } ); it( 'should remove specified text node', () => { remove( p.getChild( 0 ) ); - expect( getNodesAndText( Range.createOn( p ) ) ).to.equal( 'PP' ); + expect( getNodesAndText( Range._createOn( p ) ) ).to.equal( 'PP' ); } ); it( 'should remove any range of nodes', () => { remove( range ); - expect( getNodesAndText( Range.createIn( root.getChild( 0 ) ) ) ).to.equal( 'PggParPhhhhP' ); - expect( getNodesAndText( Range.createIn( root.getChild( 1 ) ) ) ).to.equal( 'abcxyz' ); + expect( getNodesAndText( Range._createIn( root.getChild( 0 ) ) ) ).to.equal( 'PggParPhhhhP' ); + expect( getNodesAndText( Range._createIn( root.getChild( 1 ) ) ) ).to.equal( 'abcxyz' ); } ); it( 'should create minimal number of remove operations, each with only one operation', () => { @@ -1582,20 +1582,20 @@ describe( 'Writer', () => { expect( frag.maxOffset ).to.equal( 1 ); expect( frag.childCount ).to.equal( 1 ); - expect( getNodesAndText( Range.createIn( frag.getChild( 0 ) ) ) ).to.equal( 'abcxyz' ); + expect( getNodesAndText( Range._createIn( frag.getChild( 0 ) ) ) ).to.equal( 'abcxyz' ); } ); it( 'should remove specified text node', () => { remove( p.getChild( 0 ) ); - expect( getNodesAndText( Range.createOn( p ) ) ).to.equal( 'PP' ); + expect( getNodesAndText( Range._createOn( p ) ) ).to.equal( 'PP' ); } ); it( 'should remove any range of nodes', () => { remove( range ); - expect( getNodesAndText( Range.createIn( frag.getChild( 0 ) ) ) ).to.equal( 'PggParPhhhhP' ); - expect( getNodesAndText( Range.createIn( frag.getChild( 1 ) ) ) ).to.equal( 'abcxyz' ); + expect( getNodesAndText( Range._createIn( frag.getChild( 0 ) ) ) ).to.equal( 'PggParPhhhhP' ); + expect( getNodesAndText( Range._createIn( frag.getChild( 1 ) ) ) ).to.equal( 'abcxyz' ); } ); it( 'should create minimal number of remove operations, each with only one operation', () => { @@ -1828,7 +1828,7 @@ describe( 'Writer', () => { it( 'should wrap inside document fragment', () => { const docFrag = new DocumentFragment( new Text( 'foo' ) ); - wrap( Range.createIn( docFrag ), 'p' ); + wrap( Range._createIn( docFrag ), 'p' ); expect( docFrag.maxOffset ).to.equal( 1 ); expect( docFrag.getChild( 0 ).name ).to.equal( 'p' ); @@ -1919,7 +1919,7 @@ describe( 'Writer', () => { beforeEach( () => { root = doc.createRoot(); root._appendChild( new Text( 'foo' ) ); - range = Range.createIn( root ); + range = Range._createIn( root ); } ); it( 'should throw if options.usingOperations is not defined', () => { @@ -1979,7 +1979,7 @@ describe( 'Writer', () => { it( 'should throw when trying to update existing marker in the document marker collection', () => { addMarker( 'name', { range, usingOperation: false } ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); expect( () => { addMarker( 'name', { range: range2, usingOperation: false } ); @@ -2028,12 +2028,12 @@ describe( 'Writer', () => { beforeEach( () => { root = doc.createRoot(); root._appendChild( new Text( 'foo' ) ); - range = Range.createIn( root ); + range = Range._createIn( root ); } ); it( 'should update managed marker\'s range by marker instance using operations', () => { const marker = addMarker( 'name', { range, usingOperation: true } ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); updateMarker( marker, { range: range2 } ); @@ -2048,7 +2048,7 @@ describe( 'Writer', () => { it( 'should update managed marker\'s range by marker name using operations', () => { const marker = addMarker( 'name', { range, usingOperation: true } ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); updateMarker( 'name', { range: range2 } ); @@ -2063,7 +2063,7 @@ describe( 'Writer', () => { it( 'should update managed marker\'s range by marker instance using operations and usingOperation explicitly passed', () => { const marker = addMarker( 'name', { range, usingOperation: true } ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); updateMarker( marker, { range: range2, usingOperation: true } ); @@ -2078,7 +2078,7 @@ describe( 'Writer', () => { it( 'should update managed marker\'s range by marker name using operations and usingOperation explicitly passed', () => { const marker = addMarker( 'name', { range, usingOperation: true } ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); updateMarker( 'name', { range: range2, usingOperation: true } ); @@ -2096,7 +2096,7 @@ describe( 'Writer', () => { model.on( 'applyOperation', spy ); const marker = addMarker( 'name', { range, usingOperation: false } ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); updateMarker( marker, { range: range2 } ); @@ -2131,7 +2131,7 @@ describe( 'Writer', () => { it( 'should create additional operation when marker type changes to not managed using operation and changing its range', () => { const spy = sinon.spy(); model.on( 'applyOperation', spy ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); addMarker( 'name', { range, usingOperation: true } ); updateMarker( 'name', { range: range2, usingOperation: false } ); @@ -2174,7 +2174,7 @@ describe( 'Writer', () => { it( 'should enable changing marker to be managed using operation while changing range', () => { const spy = sinon.spy(); model.on( 'applyOperation', spy ); - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); addMarker( 'name', { range, usingOperation: false } ); updateMarker( 'name', { range: range2, usingOperation: true } ); @@ -2212,7 +2212,7 @@ describe( 'Writer', () => { } ); it( 'should not change affectsData property if not provided', () => { - const range2 = Range.createFromParentsAndOffsets( root, 0, root, 0 ); + const range2 = new Range( Position._createAt( root, 0 ), Position._createAt( root, 0 ) ); addMarker( 'name', { range, affectsData: false, usingOperation: false } ); updateMarker( 'name', { range: range2 } ); @@ -2280,7 +2280,7 @@ describe( 'Writer', () => { beforeEach( () => { root = doc.createRoot(); root._appendChild( new Text( 'foo' ) ); - range = Range.createIn( root ); + range = Range._createIn( root ); } ); it( 'should remove marker from the document marker collection', () => { @@ -2570,6 +2570,102 @@ describe( 'Writer', () => { } ); } ); + describe( 'createPositionFromPath()', () => { + it( 'should call model.createPositionFromPath()', () => { + const stub = sinon.stub( model, 'createPositionFromPath' ); + + model.change( writer => { + writer.createPositionFromPath(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + + describe( 'createPositionAt()', () => { + it( 'should call model.createPositionAt()', () => { + const stub = sinon.stub( model, 'createPositionAt' ); + + model.change( writer => { + writer.createPositionAt(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + + describe( 'createPositionAfter()', () => { + it( 'should call model.createPositionAfter()', () => { + const stub = sinon.stub( model, 'createPositionAfter' ); + + model.change( writer => { + writer.createPositionAfter(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + + describe( 'createPositionBefore()', () => { + it( 'should call model.createPositionBefore()', () => { + const stub = sinon.stub( model, 'createPositionBefore' ); + + model.change( writer => { + writer.createPositionBefore(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + + describe( 'createRange()', () => { + it( 'should call model.createRange()', () => { + const stub = sinon.stub( model, 'createRange' ); + + model.change( writer => { + writer.createRange(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + + describe( 'createRangeIn()', () => { + it( 'should call model.createRangeIn()', () => { + const stub = sinon.stub( model, 'createRangeIn' ); + + model.change( writer => { + writer.createRangeIn(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + + describe( 'createRangeOn()', () => { + it( 'should call model.createRangeOn()', () => { + const stub = sinon.stub( model, 'createRangeOn' ); + + model.change( writer => { + writer.createRangeOn(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + + describe( 'createSelection()', () => { + it( 'should call model.createSelection()', () => { + const stub = sinon.stub( model, 'createSelection' ); + + model.change( writer => { + writer.createSelection(); + } ); + + sinon.assert.calledOnce( stub ); + } ); + } ); + function createText( data, attributes ) { return model.change( writer => { return writer.createText( data, attributes ); diff --git a/tests/tickets/1267.js b/tests/tickets/1267.js index 6f998aa71..10c171414 100644 --- a/tests/tickets/1267.js +++ b/tests/tickets/1267.js @@ -41,7 +41,7 @@ describe( 'Bug ckeditor5-engine#1267', () => { // Remove second paragraph where selection is placed. model.enqueueChange( 'transparent', writer => { - writer.remove( Range.createFromPositionAndShift( new Position( model.document.getRoot(), [ 1 ] ), 1 ) ); + writer.remove( Range._createFromPositionAndShift( new Position( model.document.getRoot(), [ 1 ] ), 1 ) ); } ); expect( getModelData( model ) ).to.equal( 'foo bar baz[]' ); @@ -64,7 +64,7 @@ describe( 'Bug ckeditor5-engine#1267', () => { // Remove second paragraph. model.enqueueChange( 'transparent', writer => { - writer.remove( Range.createFromPositionAndShift( new Position( model.document.getRoot(), [ 1 ] ), 1 ) ); + writer.remove( Range._createFromPositionAndShift( new Position( model.document.getRoot(), [ 1 ] ), 1 ) ); } ); // Selection attributes set by command should stay as they were. diff --git a/tests/tickets/1281.js b/tests/tickets/1281.js index b45e0b78d..3c1d0e8e8 100644 --- a/tests/tickets/1281.js +++ b/tests/tickets/1281.js @@ -47,11 +47,11 @@ describe( 'Bug ckeditor5-engine#1281', () => { expect( selRanges.length ).to.equal( 2 ); - assertPositions( Position.createAt( thirdParagraph, 0 ), selRanges[ 0 ].start ); - assertPositions( Position.createAt( thirdParagraph, 'end' ), selRanges[ 0 ].end ); + assertPositions( Position._createAt( thirdParagraph, 0 ), selRanges[ 0 ].start ); + assertPositions( Position._createAt( thirdParagraph, 'end' ), selRanges[ 0 ].end ); - assertPositions( Position.createAt( fourthParagraph, 0 ), selRanges[ 1 ].start ); - assertPositions( Position.createAt( fourthParagraph, 'end' ), selRanges[ 1 ].end ); + assertPositions( Position._createAt( fourthParagraph, 0 ), selRanges[ 1 ].start ); + assertPositions( Position._createAt( fourthParagraph, 'end' ), selRanges[ 1 ].end ); } ); it( 'does not throw an error when content before the selection is being removed (last element is selected)', () => { diff --git a/tests/tickets/1323.js b/tests/tickets/1323.js index da5f22e4f..64921040a 100644 --- a/tests/tickets/1323.js +++ b/tests/tickets/1323.js @@ -7,7 +7,6 @@ import EditingController from '../../src/controller/editingcontroller'; import Model from '../../src/model/model'; import ModelText from '../../src/model/text'; -import ModelRange from '../../src/model/range'; import MarkerOperation from '../../src/model/operation/markeroperation'; @@ -20,7 +19,7 @@ describe( 'Bug ckeditor5-engine@1323', () => { editing = new EditingController( model ); root = model.document.createRoot(); root._appendChild( new ModelText( 'foo' ) ); - range = ModelRange.createFromParentsAndOffsets( root, 0, root, 0 ); + range = model.createRange( model.createPositionAt( root, 0 ), model.createPositionAt( root, 0 ) ); } ); afterEach( () => { diff --git a/tests/utils/bindtwostepcarettoattribute.js b/tests/utils/bindtwostepcarettoattribute.js index a3c867f42..ee583e50d 100644 --- a/tests/utils/bindtwostepcarettoattribute.js +++ b/tests/utils/bindtwostepcarettoattribute.js @@ -789,7 +789,7 @@ describe( 'bindTwoStepCaretToAttribute()', () => { const nextBlock = position.parent.nextSibling; if ( nextBlock ) { - writer.setSelection( Position.createAt( nextBlock, 0 ) ); + writer.setSelection( Position._createAt( nextBlock, 0 ) ); } } else { writer.setSelection( selection.getFirstPosition().getShiftedBy( 1 ) ); @@ -801,7 +801,7 @@ describe( 'bindTwoStepCaretToAttribute()', () => { const previousBlock = position.parent.previousSibling; if ( previousBlock ) { - writer.setSelection( Position.createAt( previousBlock, 'end' ) ); + writer.setSelection( Position._createAt( previousBlock, 'end' ) ); } } else { writer.setSelection( selection.getFirstPosition().getShiftedBy( -1 ) ); diff --git a/tests/view/documentselection.js b/tests/view/documentselection.js index 78ca8a11d..0c543e558 100644 --- a/tests/view/documentselection.js +++ b/tests/view/documentselection.js @@ -14,19 +14,22 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import count from '@ckeditor/ckeditor5-utils/src/count'; import createViewRoot from './_utils/createroot'; import { parse } from '../../src/dev-utils/view'; +import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; describe( 'DocumentSelection', () => { let documentSelection, el, range1, range2, range3; + testUtils.createSinonSandbox(); + beforeEach( () => { const text = new Text( 'xxxxxxxxxxxxxxxxxxxx' ); el = new Element( 'p', null, text ); documentSelection = new DocumentSelection(); - range1 = Range.createFromParentsAndOffsets( text, 5, text, 10 ); - range2 = Range.createFromParentsAndOffsets( text, 1, text, 2 ); - range3 = Range.createFromParentsAndOffsets( text, 12, text, 14 ); + range1 = Range._createFromParentsAndOffsets( text, 5, text, 10 ); + range2 = Range._createFromParentsAndOffsets( text, 1, text, 2 ); + range3 = Range._createFromParentsAndOffsets( text, 12, text, 14 ); } ); describe( 'constructor()', () => { @@ -118,7 +121,7 @@ describe( 'DocumentSelection', () => { it( 'should throw an error when ranges intersects', () => { const text = el.getChild( 0 ); - const range2 = Range.createFromParentsAndOffsets( text, 7, text, 15 ); + const range2 = Range._createFromParentsAndOffsets( text, 7, text, 15 ); expect( () => { // eslint-disable-next-line no-new @@ -198,7 +201,7 @@ describe( 'DocumentSelection', () => { } ); it( 'throws if there are no ranges in selection', () => { - const endPos = Position.createAt( el, 'end' ); + const endPos = Position._createAt( el, 'end' ); expect( () => { documentSelection._setFocus( endPos ); @@ -206,8 +209,8 @@ describe( 'DocumentSelection', () => { } ); it( 'modifies existing collapsed selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); documentSelection._setTo( startPos ); @@ -218,8 +221,8 @@ describe( 'DocumentSelection', () => { } ); it( 'makes existing collapsed selection a backward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 0 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 0 ); documentSelection._setTo( startPos ); @@ -231,9 +234,9 @@ describe( 'DocumentSelection', () => { } ); it( 'modifies existing non-collapsed selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 3 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 3 ); documentSelection._setTo( new Range( startPos, endPos ) ); @@ -244,9 +247,9 @@ describe( 'DocumentSelection', () => { } ); it( 'makes existing non-collapsed selection a backward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 0 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 0 ); documentSelection._setTo( new Range( startPos, endPos ) ); @@ -258,9 +261,9 @@ describe( 'DocumentSelection', () => { } ); it( 'makes existing backward selection a forward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 3 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 3 ); documentSelection._setTo( new Range( startPos, endPos ), { backward: true } ); @@ -272,9 +275,9 @@ describe( 'DocumentSelection', () => { } ); it( 'modifies existing backward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 0 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 0 ); documentSelection._setTo( new Range( startPos, endPos ), { backward: true } ); @@ -287,12 +290,12 @@ describe( 'DocumentSelection', () => { it( 'modifies only the last range', () => { // Offsets are chosen in this way that the order of adding ranges must count, not their document order. - const startPos1 = Position.createAt( el, 4 ); - const endPos1 = Position.createAt( el, 5 ); - const startPos2 = Position.createAt( el, 1 ); - const endPos2 = Position.createAt( el, 2 ); + const startPos1 = Position._createAt( el, 4 ); + const endPos1 = Position._createAt( el, 5 ); + const startPos2 = Position._createAt( el, 1 ); + const endPos2 = Position._createAt( el, 2 ); - const newEndPos = Position.createAt( el, 0 ); + const newEndPos = Position._createAt( el, 0 ); documentSelection._setTo( [ new Range( startPos1, endPos1 ), @@ -313,8 +316,8 @@ describe( 'DocumentSelection', () => { } ); it( 'collapses the selection when extending to the anchor', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); documentSelection._setTo( new Range( startPos, endPos ) ); @@ -323,42 +326,26 @@ describe( 'DocumentSelection', () => { expect( documentSelection.focus.compareWith( startPos ) ).to.equal( 'same' ); expect( documentSelection.isCollapsed ).to.be.true; } ); - - it( 'uses Position.createAt', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 4 ); - - const spy = sinon.stub( Position, 'createAt' ).returns( newEndPos ); - - documentSelection._setTo( new Range( startPos, endPos ) ); - documentSelection._setFocus( el, 'end' ); - - expect( spy.calledOnce ).to.be.true; - expect( documentSelection.focus.compareWith( newEndPos ) ).to.equal( 'same' ); - - Position.createAt.restore(); - } ); } ); describe( 'isCollapsed', () => { it( 'should return true when there is single collapsed range', () => { - const range = Range.createFromParentsAndOffsets( el, 5, el, 5 ); + const range = Range._createFromParentsAndOffsets( el, 5, el, 5 ); documentSelection._setTo( range ); expect( documentSelection.isCollapsed ).to.be.true; } ); it( 'should return false when there are multiple ranges', () => { - const range1 = Range.createFromParentsAndOffsets( el, 5, el, 5 ); - const range2 = Range.createFromParentsAndOffsets( el, 15, el, 15 ); + const range1 = Range._createFromParentsAndOffsets( el, 5, el, 5 ); + const range2 = Range._createFromParentsAndOffsets( el, 15, el, 15 ); documentSelection._setTo( [ range1, range2 ] ); expect( documentSelection.isCollapsed ).to.be.false; } ); it( 'should return false when there is not collapsed range', () => { - const range = Range.createFromParentsAndOffsets( el, 15, el, 16 ); + const range = Range._createFromParentsAndOffsets( el, 15, el, 16 ); documentSelection._setTo( range ); expect( documentSelection.isCollapsed ).to.be.false; @@ -381,8 +368,8 @@ describe( 'DocumentSelection', () => { describe( 'isBackward', () => { it( 'is defined by the last added range', () => { - const range1 = Range.createFromParentsAndOffsets( el, 5, el, 10 ); - const range2 = Range.createFromParentsAndOffsets( el, 15, el, 16 ); + const range1 = Range._createFromParentsAndOffsets( el, 5, el, 10 ); + const range2 = Range._createFromParentsAndOffsets( el, 15, el, 16 ); documentSelection._setTo( range1, { backward: true } ); expect( documentSelection ).to.have.property( 'isBackward', true ); @@ -392,7 +379,7 @@ describe( 'DocumentSelection', () => { } ); it( 'is false when last range is collapsed', () => { - const range = Range.createFromParentsAndOffsets( el, 5, el, 5 ); + const range = Range._createFromParentsAndOffsets( el, 5, el, 5 ); documentSelection._setTo( range, { backward: true } ); @@ -693,10 +680,10 @@ describe( 'DocumentSelection', () => { const span2 = p2.getChild( 0 ); //

[{]}

[{xx}]

- const rangeA1 = Range.createFromParentsAndOffsets( p1, 0, span1, 0 ); - const rangeB1 = Range.createFromParentsAndOffsets( span1, 0, p1, 1 ); - const rangeA2 = Range.createFromParentsAndOffsets( p2, 0, p2, 1 ); - const rangeB2 = Range.createFromParentsAndOffsets( span2, 0, span2, 1 ); + const rangeA1 = Range._createFromParentsAndOffsets( p1, 0, span1, 0 ); + const rangeB1 = Range._createFromParentsAndOffsets( span1, 0, p1, 1 ); + const rangeA2 = Range._createFromParentsAndOffsets( p2, 0, p2, 1 ); + const rangeB2 = Range._createFromParentsAndOffsets( span2, 0, span2, 1 ); documentSelection._setTo( [ rangeA1, rangeA2 ] ); @@ -721,10 +708,10 @@ describe( 'DocumentSelection', () => { const span2 = p2.getChild( 0 ); //

[{]}

[{xx}]

- const rangeA1 = Range.createFromParentsAndOffsets( p1, 0, span1, 0 ); - const rangeB1 = Range.createFromParentsAndOffsets( span1, 0, p1, 1 ); - const rangeA2 = Range.createFromParentsAndOffsets( p2, 0, p2, 1 ); - const rangeB2 = Range.createFromParentsAndOffsets( span2, 0, span2, 1 ); + const rangeA1 = Range._createFromParentsAndOffsets( p1, 0, span1, 0 ); + const rangeB1 = Range._createFromParentsAndOffsets( span1, 0, p1, 1 ); + const rangeA2 = Range._createFromParentsAndOffsets( p2, 0, p2, 1 ); + const rangeB2 = Range._createFromParentsAndOffsets( span2, 0, span2, 1 ); documentSelection._setTo( [ rangeA1, rangeA2 ] ); @@ -1009,7 +996,7 @@ describe( 'DocumentSelection', () => { it( 'should throw when range is intersecting with already added range', () => { const text = el.getChild( 0 ); - const range2 = Range.createFromParentsAndOffsets( text, 7, text, 15 ); + const range2 = Range._createFromParentsAndOffsets( text, 7, text, 15 ); expect( () => { documentSelection._setTo( [ range1, range2 ] ); @@ -1079,7 +1066,7 @@ describe( 'DocumentSelection', () => { const element = new Element( 'p' ); root._appendChild( element ); - documentSelection._setTo( Range.createFromParentsAndOffsets( element, 0, element, 0 ) ); + documentSelection._setTo( Range._createFromParentsAndOffsets( element, 0, element, 0 ) ); expect( documentSelection.editableElement ).to.equal( root ); } ); diff --git a/tests/view/domconverter/dom-to-view.js b/tests/view/domconverter/dom-to-view.js index c3bf0cd76..3bf331bfc 100644 --- a/tests/view/domconverter/dom-to-view.js +++ b/tests/view/domconverter/dom-to-view.js @@ -871,7 +871,7 @@ describe( 'DomConverter', () => { } ); describe( 'domRangeToView()', () => { - it( 'should converter DOM range', () => { + it( 'should convert DOM range', () => { const domFoo = document.createTextNode( 'foo' ); const domBar = document.createTextNode( 'bar' ); const domB = createElement( document, 'b', null, domBar ); diff --git a/tests/view/downcastwriter/breakattributes.js b/tests/view/downcastwriter/breakattributes.js index a3e94c74e..1173fe96a 100644 --- a/tests/view/downcastwriter/breakattributes.js +++ b/tests/view/downcastwriter/breakattributes.js @@ -154,7 +154,7 @@ describe( 'DowncastWriter', () => { const p2 = new ContainerElement( 'p' ); expect( () => { - writer.breakAttributes( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) ); + writer.breakAttributes( Range._createFromParentsAndOffsets( p1, 0, p2, 0 ) ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); @@ -162,7 +162,7 @@ describe( 'DowncastWriter', () => { const el = new AttributeElement( 'b' ); expect( () => { - writer.breakAttributes( Range.createFromParentsAndOffsets( el, 0, el, 0 ) ); + writer.breakAttributes( Range._createFromParentsAndOffsets( el, 0, el, 0 ) ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); @@ -252,7 +252,7 @@ describe( 'DowncastWriter', () => { const img = new EmptyElement( 'img' ); const b = new AttributeElement( 'b' ); new ContainerElement( 'p', null, [ img, b ] ); // eslint-disable-line no-new - const range = Range.createFromParentsAndOffsets( img, 0, b, 0 ); + const range = Range._createFromParentsAndOffsets( img, 0, b, 0 ); expect( () => { writer.breakAttributes( range ); @@ -273,7 +273,7 @@ describe( 'DowncastWriter', () => { const span = new UIElement( 'span' ); const b = new AttributeElement( 'b' ); new ContainerElement( 'p', null, [ span, b ] ); // eslint-disable-line no-new - const range = Range.createFromParentsAndOffsets( span, 0, b, 0 ); + const range = Range._createFromParentsAndOffsets( span, 0, b, 0 ); expect( () => { writer.breakAttributes( range ); diff --git a/tests/view/downcastwriter/breakcontainer.js b/tests/view/downcastwriter/breakcontainer.js index 6d0d98c98..f1d585330 100644 --- a/tests/view/downcastwriter/breakcontainer.js +++ b/tests/view/downcastwriter/breakcontainer.js @@ -73,7 +73,7 @@ describe( 'DowncastWriter', () => { it( 'should throw if position parent is root', () => { const element = new ContainerElement( 'div' ); - const position = Position.createAt( element, 0 ); + const position = Position._createAt( element, 0 ); expect( () => { writer.breakContainer( position ); diff --git a/tests/view/downcastwriter/clear.js b/tests/view/downcastwriter/clear.js index 755bed464..3c135d530 100644 --- a/tests/view/downcastwriter/clear.js +++ b/tests/view/downcastwriter/clear.js @@ -39,7 +39,7 @@ describe( 'DowncastWriter', () => { const p2 = new ContainerElement( 'p' ); expect( () => { - writer.clear( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) ); + writer.clear( Range._createFromParentsAndOffsets( p1, 0, p2, 0 ) ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); @@ -47,7 +47,7 @@ describe( 'DowncastWriter', () => { const el = new AttributeElement( 'b' ); expect( () => { - writer.clear( Range.createFromParentsAndOffsets( el, 0, el, 0 ) ); + writer.clear( Range._createFromParentsAndOffsets( el, 0, el, 0 ) ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); diff --git a/tests/view/downcastwriter/move.js b/tests/view/downcastwriter/move.js index 761b36ad1..85b4433b3 100644 --- a/tests/view/downcastwriter/move.js +++ b/tests/view/downcastwriter/move.js @@ -118,7 +118,7 @@ describe( 'DowncastWriter', () => { it( 'should correctly move text nodes inside same parent', () => { const { view, selection } = parse( '[a]bc' ); - const newRange = writer.move( selection.getFirstRange(), Position.createAt( view, 2 ) ); + const newRange = writer.move( selection.getFirstRange(), Position._createAt( view, 2 ) ); const expectedView = 'b[a}c'; expect( stringify( view, newRange, { showType: true } ) ).to.equal( expectedView ); @@ -130,7 +130,7 @@ describe( 'DowncastWriter', () => { ); const viewText = view.getChild( 3 ); - const newRange = writer.move( selection.getFirstRange(), Position.createAt( viewText, 1 ) ); + const newRange = writer.move( selection.getFirstRange(), Position._createAt( viewText, 1 ) ); expect( stringify( view, newRange, { showType: true } ) ).to.equal( 'ady[bxxc]y' @@ -149,7 +149,7 @@ describe( 'DowncastWriter', () => { it( 'should throw if trying to move to EmptyElement', () => { const srcAttribute = new AttributeElement( 'b' ); const srcContainer = new ContainerElement( 'p', null, srcAttribute ); - const srcRange = Range.createFromParentsAndOffsets( srcContainer, 0, srcContainer, 1 ); + const srcRange = Range._createFromParentsAndOffsets( srcContainer, 0, srcContainer, 1 ); const dstEmpty = new EmptyElement( 'img' ); new ContainerElement( 'p', null, dstEmpty ); // eslint-disable-line no-new @@ -172,7 +172,7 @@ describe( 'DowncastWriter', () => { it( 'should throw if trying to move to UIElement', () => { const srcAttribute = new AttributeElement( 'b' ); const srcContainer = new ContainerElement( 'p', null, srcAttribute ); - const srcRange = Range.createFromParentsAndOffsets( srcContainer, 0, srcContainer, 1 ); + const srcRange = Range._createFromParentsAndOffsets( srcContainer, 0, srcContainer, 1 ); const dstUI = new UIElement( 'span' ); new ContainerElement( 'p', null, dstUI ); // eslint-disable-line no-new @@ -204,11 +204,11 @@ describe( 'DowncastWriter', () => { expect( mapper.markerNameToElements( 'foo' ).size ).to.equal( 2 ); - writer.remove( Range.createOn( attrElemA ) ); + writer.remove( writer.createRangeOn( attrElemA ) ); expect( mapper.markerNameToElements( 'foo' ).size ).to.equal( 1 ); - writer.move( Range.createOn( attrElemB ), new Position( dstContainer, 0 ) ); + writer.move( writer.createRangeOn( attrElemB ), new Position( dstContainer, 0 ) ); expect( mapper.markerNameToElements( 'foo' ).size ).to.equal( 1 ); } ); diff --git a/tests/view/downcastwriter/remove.js b/tests/view/downcastwriter/remove.js index 0dd573505..969912a21 100644 --- a/tests/view/downcastwriter/remove.js +++ b/tests/view/downcastwriter/remove.js @@ -45,7 +45,7 @@ describe( 'DowncastWriter', () => { const p2 = new ContainerElement( 'p' ); expect( () => { - writer.remove( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) ); + writer.remove( Range._createFromParentsAndOffsets( p1, 0, p2, 0 ) ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); @@ -53,13 +53,13 @@ describe( 'DowncastWriter', () => { const el = new AttributeElement( 'b' ); expect( () => { - writer.remove( Range.createFromParentsAndOffsets( el, 0, el, 0 ) ); + writer.remove( Range._createFromParentsAndOffsets( el, 0, el, 0 ) ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); it( 'should return empty DocumentFragment when range is collapsed', () => { const p = new ContainerElement( 'p' ); - const range = Range.createFromParentsAndOffsets( p, 0, p, 0 ); + const range = Range._createFromParentsAndOffsets( p, 0, p, 0 ); const fragment = writer.remove( range ); expect( fragment ).to.be.instanceof( DocumentFragment ); @@ -131,7 +131,7 @@ describe( 'DowncastWriter', () => { const emptyElement = new EmptyElement( 'img' ); const attributeElement = new AttributeElement( 'b' ); new ContainerElement( 'p', null, [ emptyElement, attributeElement ] ); // eslint-disable-line no-new - const range = Range.createFromParentsAndOffsets( emptyElement, 0, attributeElement, 0 ); + const range = Range._createFromParentsAndOffsets( emptyElement, 0, attributeElement, 0 ); expect( () => { writer.remove( range ); @@ -150,7 +150,7 @@ describe( 'DowncastWriter', () => { const uiElement = new UIElement( 'span' ); const attributeElement = new AttributeElement( 'b' ); new ContainerElement( 'p', null, [ uiElement, attributeElement ] ); // eslint-disable-line no-new - const range = Range.createFromParentsAndOffsets( uiElement, 0, attributeElement, 0 ); + const range = Range._createFromParentsAndOffsets( uiElement, 0, attributeElement, 0 ); expect( () => { writer.remove( range ); diff --git a/tests/view/downcastwriter/unwrap.js b/tests/view/downcastwriter/unwrap.js index 83fe2af5d..1a1406450 100644 --- a/tests/view/downcastwriter/unwrap.js +++ b/tests/view/downcastwriter/unwrap.js @@ -84,7 +84,7 @@ describe( 'DowncastWriter', () => { const b = new AttributeElement( 'b' ); expect( () => { - writer.unwrap( Range.createFromParentsAndOffsets( el, 0, el, 0 ), b ); + writer.unwrap( Range._createFromParentsAndOffsets( el, 0, el, 0 ), b ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); @@ -347,7 +347,7 @@ describe( 'DowncastWriter', () => { const empty = new EmptyElement( 'img' ); const attribute = new AttributeElement( 'b' ); const container = new ContainerElement( 'p', null, [ empty, attribute ] ); - const range = Range.createFromParentsAndOffsets( empty, 0, container, 2 ); + const range = Range._createFromParentsAndOffsets( empty, 0, container, 2 ); expect( () => { writer.unwrap( range, attribute ); @@ -366,7 +366,7 @@ describe( 'DowncastWriter', () => { const uiElement = new UIElement( 'span' ); const attribute = new AttributeElement( 'b' ); const container = new ContainerElement( 'p', null, [ uiElement, attribute ] ); - const range = Range.createFromParentsAndOffsets( uiElement, 0, container, 2 ); + const range = Range._createFromParentsAndOffsets( uiElement, 0, container, 2 ); expect( () => { writer.unwrap( range, attribute ); @@ -378,8 +378,8 @@ describe( 'DowncastWriter', () => { const attribute = writer.createAttributeElement( 'span', null, { id: 'foo' } ); const container = writer.createContainerElement( 'div' ); - writer.insert( Position.createAt( container, 0 ), attribute ); - writer.unwrap( Range.createOn( attribute ), unwrapper ); + writer.insert( writer.createPositionAt( container, 0 ), attribute ); + writer.unwrap( Range._createOn( attribute ), unwrapper ); expect( stringify( container, null, { showType: false, showPriority: false } ) ).to.equal( '
' ); } ); @@ -389,8 +389,8 @@ describe( 'DowncastWriter', () => { const attribute = writer.createAttributeElement( 'span', { foo: 'foo' }, { id: 'foo' } ); const container = writer.createContainerElement( 'div' ); - writer.insert( Position.createAt( container, 0 ), attribute ); - writer.unwrap( Range.createOn( attribute ), unwrapper ); + writer.insert( writer.createPositionAt( container, 0 ), attribute ); + writer.unwrap( writer.createRangeOn( attribute ), unwrapper ); expect( stringify( container, null, { showType: false, showPriority: false } ) ).to.equal( '
' ); } ); @@ -403,8 +403,8 @@ describe( 'DowncastWriter', () => { const attribute = writer.createAttributeElement( 'span', { foo: 'foo', bar: 'bar' }, { id: 'id' } ); const container = writer.createContainerElement( 'div' ); - writer.insert( Position.createAt( container, 0 ), attribute ); - writer.unwrap( Range.createOn( attribute ), unwrapper ); + writer.insert( writer.createPositionAt( container, 0 ), attribute ); + writer.unwrap( writer.createRangeOn( attribute ), unwrapper ); const view = stringify( container, null, { showType: false, showPriority: false } ); expect( view ).to.equal( '
' ); @@ -415,8 +415,8 @@ describe( 'DowncastWriter', () => { const attribute = writer.createAttributeElement( 'span', { foo: 'foo', bar: 'bar' } ); const container = writer.createContainerElement( 'div' ); - writer.insert( Position.createAt( container, 0 ), attribute ); - writer.unwrap( Range.createOn( attribute ), unwrapper ); + writer.insert( writer.createPositionAt( container, 0 ), attribute ); + writer.unwrap( writer.createRangeOn( attribute ), unwrapper ); const view = stringify( container, null, { showType: false, showPriority: false } ); expect( view ).to.equal( '
' ); @@ -427,8 +427,8 @@ describe( 'DowncastWriter', () => { const attribute = writer.createAttributeElement( 'span', { foo: 'foo', bar: 'bar' }, { id: 'b' } ); const container = writer.createContainerElement( 'div' ); - writer.insert( Position.createAt( container, 0 ), attribute ); - writer.unwrap( Range.createOn( attribute ), unwrapper ); + writer.insert( writer.createPositionAt( container, 0 ), attribute ); + writer.unwrap( writer.createRangeOn( attribute ), unwrapper ); const view = stringify( container, null, { showType: false, showPriority: false } ); expect( view ).to.equal( '
' ); diff --git a/tests/view/downcastwriter/wrap.js b/tests/view/downcastwriter/wrap.js index 14bdbe424..85ba35547 100644 --- a/tests/view/downcastwriter/wrap.js +++ b/tests/view/downcastwriter/wrap.js @@ -91,7 +91,7 @@ describe( 'DowncastWriter', () => { const b = new AttributeElement( 'b' ); expect( () => { - writer.wrap( Range.createFromParentsAndOffsets( el, 0, el, 0 ), b ); + writer.wrap( Range._createFromParentsAndOffsets( el, 0, el, 0 ), b ); } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); @@ -356,7 +356,7 @@ describe( 'DowncastWriter', () => { it( 'should throw if range is inside EmptyElement', () => { const emptyElement = new EmptyElement( 'img' ); const container = new ContainerElement( 'p', null, emptyElement ); - const range = Range.createFromParentsAndOffsets( emptyElement, 0, container, 1 ); + const range = Range._createFromParentsAndOffsets( emptyElement, 0, container, 1 ); expect( () => { writer.wrap( range, new AttributeElement( 'b' ) ); @@ -374,7 +374,7 @@ describe( 'DowncastWriter', () => { it( 'should throw if range is inside UIElement', () => { const uiElement = new UIElement( 'span' ); const container = new ContainerElement( 'p', null, uiElement ); - const range = Range.createFromParentsAndOffsets( uiElement, 0, container, 1 ); + const range = Range._createFromParentsAndOffsets( uiElement, 0, container, 1 ); expect( () => { writer.wrap( range, new AttributeElement( 'b' ) ); diff --git a/tests/view/downcastwriter/writer.js b/tests/view/downcastwriter/writer.js index b9b6a477a..e7de22fa2 100644 --- a/tests/view/downcastwriter/writer.js +++ b/tests/view/downcastwriter/writer.js @@ -9,6 +9,8 @@ import EditableElement from '../../../src/view/editableelement'; import ViewPosition from '../../../src/view/position'; import ViewRange from '../../../src/view/range'; import createViewRoot from '../_utils/createroot'; +import ViewElement from '../../../src/view/element'; +import ViewSelection from '../../../src/view/selection'; describe( 'DowncastWriter', () => { let writer, attributes, root, doc; @@ -22,7 +24,7 @@ describe( 'DowncastWriter', () => { describe( 'setSelection()', () => { it( 'should set document view selection', () => { - const position = ViewPosition.createAt( root, 0 ); + const position = ViewPosition._createAt( root, 0 ); writer.setSelection( position ); const ranges = Array.from( doc.selection.getRanges() ); @@ -33,7 +35,7 @@ describe( 'DowncastWriter', () => { } ); it( 'should be able to set fake selection', () => { - const position = ViewPosition.createAt( root, 0 ); + const position = ViewPosition._createAt( root, 0 ); writer.setSelection( position, { fake: true, label: 'foo' } ); expect( doc.selection.isFake ).to.be.true; @@ -43,7 +45,7 @@ describe( 'DowncastWriter', () => { describe( 'setSelectionFocus()', () => { it( 'should use selection._setFocus method internally', () => { - const position = ViewPosition.createAt( root, 0 ); + const position = ViewPosition._createAt( root, 0 ); writer.setSelection( position ); const spy = sinon.spy( writer.document.selection, '_setFocus' ); @@ -256,23 +258,79 @@ describe( 'DowncastWriter', () => { } ); } ); + describe( 'createPositionAt()', () => { + it( 'should return instance of Position', () => { + doc.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( writer.createPositionAt( doc.getRoot(), 0 ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createPositionAfter()', () => { + it( 'should return instance of Position', () => { + doc.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( writer.createPositionAfter( doc.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createPositionBefore()', () => { + it( 'should return instance of Position', () => { + doc.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( writer.createPositionBefore( doc.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createRange()', () => { + it( 'should return instance of Range', () => { + doc.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( writer.createRange( writer.createPositionAt( doc.getRoot(), 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createRangeIn()', () => { + it( 'should return instance of Range', () => { + doc.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( writer.createRangeIn( doc.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createRangeOn()', () => { + it( 'should return instance of Range', () => { + doc.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( writer.createRangeOn( doc.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createSelection()', () => { + it( 'should return instance of Selection', () => { + doc.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( writer.createSelection() ).to.be.instanceof( ViewSelection ); + } ); + } ); + describe( 'manages AttributeElement#_clonesGroup', () => { it( 'should return all clones of a broken attribute element with id', () => { const text = writer.createText( 'abccccde' ); - writer.insert( ViewPosition.createAt( root, 0 ), text ); + writer.insert( ViewPosition._createAt( root, 0 ), text ); const span = writer.createAttributeElement( 'span', null, { id: 'foo' } ); span._priority = 20; //
abccccde
- writer.wrap( ViewRange.createFromParentsAndOffsets( text, 2, text, 6 ), span ); + writer.wrap( ViewRange._createFromParentsAndOffsets( text, 2, text, 6 ), span ); const i = writer.createAttributeElement( 'i' ); //
abcccde
writer.wrap( - ViewRange.createFromParentsAndOffsets( + ViewRange._createFromParentsAndOffsets( root.getChild( 0 ), 1, root.getChild( 1 ).getChild( 0 ), 1 ), @@ -281,7 +339,7 @@ describe( 'DowncastWriter', () => { //
abccccde
writer.wrap( - ViewRange.createFromParentsAndOffsets( + ViewRange._createFromParentsAndOffsets( root.getChild( 2 ).getChild( 0 ), 1, root.getChild( 3 ), 1 ), @@ -289,7 +347,7 @@ describe( 'DowncastWriter', () => { ); // Find all spans. - const allSpans = Array.from( ViewRange.createIn( root ).getItems() ).filter( element => element.is( 'span' ) ); + const allSpans = Array.from( ViewRange._createIn( root ).getItems() ).filter( element => element.is( 'span' ) ); // For each of the spans created above... for ( const oneOfAllSpans of allSpans ) { @@ -308,13 +366,13 @@ describe( 'DowncastWriter', () => { it( 'should not create groups for attribute elements that are not created in document root', () => { const p = writer.createContainerElement( 'p' ); const foo = writer.createText( 'foo' ); - writer.insert( ViewPosition.createAt( p, 0 ), foo ); + writer.insert( ViewPosition._createAt( p, 0 ), foo ); //

foo

const span = writer.createAttributeElement( 'span', null, { id: 'span' } ); //

foo

- writer.wrap( ViewRange.createFromParentsAndOffsets( foo, 0, foo, 3 ), span ); + writer.wrap( ViewRange._createFromParentsAndOffsets( foo, 0, foo, 3 ), span ); // Find the span. const createdSpan = p.getChild( 0 ); @@ -325,16 +383,16 @@ describe( 'DowncastWriter', () => { it( 'should add attribute elements to clone groups deeply', () => { const p = writer.createContainerElement( 'p' ); const foo = writer.createText( 'foo' ); - writer.insert( ViewPosition.createAt( p, 0 ), foo ); + writer.insert( ViewPosition._createAt( p, 0 ), foo ); //

foo

const span = writer.createAttributeElement( 'span', null, { id: 'span' } ); //

foo

- writer.wrap( ViewRange.createFromParentsAndOffsets( foo, 0, foo, 3 ), span ); + writer.wrap( ViewRange._createFromParentsAndOffsets( foo, 0, foo, 3 ), span ); //

foo

- writer.insert( ViewPosition.createAt( root, 0 ), p ); + writer.insert( ViewPosition._createAt( root, 0 ), p ); // Find the span. const createdSpan = p.getChild( 0 ); @@ -348,22 +406,22 @@ describe( 'DowncastWriter', () => { const foo = writer.createText( 'foo' ); const bar = writer.createText( 'bar' ); - writer.insert( ViewPosition.createAt( root, 0 ), p1 ); - writer.insert( ViewPosition.createAt( root, 1 ), p2 ); - writer.insert( ViewPosition.createAt( p1, 0 ), foo ); - writer.insert( ViewPosition.createAt( p2, 0 ), bar ); + writer.insert( ViewPosition._createAt( root, 0 ), p1 ); + writer.insert( ViewPosition._createAt( root, 1 ), p2 ); + writer.insert( ViewPosition._createAt( p1, 0 ), foo ); + writer.insert( ViewPosition._createAt( p2, 0 ), bar ); //

foo

bar

const span = writer.createAttributeElement( 'span', null, { id: 'span' } ); //

foo

bar

- writer.wrap( ViewRange.createFromParentsAndOffsets( foo, 2, foo, 3 ), span ); + writer.wrap( ViewRange._createFromParentsAndOffsets( foo, 2, foo, 3 ), span ); //

foo

bar

- writer.wrap( ViewRange.createFromParentsAndOffsets( bar, 0, bar, 1 ), span ); + writer.wrap( ViewRange._createFromParentsAndOffsets( bar, 0, bar, 1 ), span ); //

bar

- writer.remove( ViewRange.createOn( p1 ) ); + writer.remove( ViewRange._createOn( p1 ) ); // Find the span. const spanInTree = p2.getChild( 0 ); diff --git a/tests/view/editableelement.js b/tests/view/editableelement.js index 52b7313ae..bb3542347 100644 --- a/tests/view/editableelement.js +++ b/tests/view/editableelement.js @@ -76,8 +76,8 @@ describe( 'EditableElement', () => { } ); it( 'should change isFocused when selection changes', () => { - const rangeMain = Range.createFromParentsAndOffsets( viewMain, 0, viewMain, 0 ); - const rangeHeader = Range.createFromParentsAndOffsets( viewHeader, 0, viewHeader, 0 ); + const rangeMain = Range._createFromParentsAndOffsets( viewMain, 0, viewMain, 0 ); + const rangeHeader = Range._createFromParentsAndOffsets( viewHeader, 0, viewHeader, 0 ); docMock.selection._setTo( rangeMain ); docMock.isFocused = true; @@ -91,8 +91,8 @@ describe( 'EditableElement', () => { } ); it( 'should change isFocused when document.isFocus changes', () => { - const rangeMain = Range.createFromParentsAndOffsets( viewMain, 0, viewMain, 0 ); - const rangeHeader = Range.createFromParentsAndOffsets( viewHeader, 0, viewHeader, 0 ); + const rangeMain = Range._createFromParentsAndOffsets( viewMain, 0, viewMain, 0 ); + const rangeHeader = Range._createFromParentsAndOffsets( viewHeader, 0, viewHeader, 0 ); docMock.selection._setTo( rangeMain ); docMock.isFocused = true; diff --git a/tests/view/manual/fakeselection.js b/tests/view/manual/fakeselection.js index 3e3facc18..fc31bbb86 100644 --- a/tests/view/manual/fakeselection.js +++ b/tests/view/manual/fakeselection.js @@ -41,7 +41,7 @@ viewDocument.on( 'mouseup', ( evt, data ) => { console.log( 'Making selection around the .' ); view.change( writer => { - writer.setSelection( ViewRange.createOn( viewStrong ), { fake: true, label: 'fake selection over bar' } ); + writer.setSelection( ViewRange._createOn( viewStrong ), { fake: true, label: 'fake selection over bar' } ); } ); data.preventDefault(); diff --git a/tests/view/manual/focus.js b/tests/view/manual/focus.js index 1362634e8..56a66c52a 100644 --- a/tests/view/manual/focus.js +++ b/tests/view/manual/focus.js @@ -28,13 +28,13 @@ view.change( writer => { text1 = writer.createText( 'Foo bar baz' ); text2 = writer.createText( 'Foo bar baz' ); - writer.insert( ViewPosition.createAt( editable1 ), text1 ); - writer.insert( ViewPosition.createAt( editable2 ), text2 ); + writer.insert( ViewPosition._createAt( editable1 ), text1 ); + writer.insert( ViewPosition._createAt( editable2 ), text2 ); } ); document.getElementById( 'button1' ).addEventListener( 'click', () => { view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( text1, 4, text1, 7 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( text1, 4, text1, 7 ) ); } ); view.focus(); @@ -42,7 +42,7 @@ document.getElementById( 'button1' ).addEventListener( 'click', () => { document.getElementById( 'button2' ).addEventListener( 'click', () => { view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( text2, 0, text2, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( text2, 0, text2, 3 ) ); } ); view.focus(); diff --git a/tests/view/manual/focusobserver.js b/tests/view/manual/focusobserver.js index acc032ef4..ba6b6ba09 100644 --- a/tests/view/manual/focusobserver.js +++ b/tests/view/manual/focusobserver.js @@ -6,7 +6,6 @@ /* globals console, document */ import View from '../../../src/view/view'; -import Position from '../../../src/view/position'; import createViewRoot from '../_utils/createroot'; const view = new View(); @@ -31,8 +30,8 @@ viewDocument.on( 'selectionChange', ( evt, data ) => { } ); view.change( writer => { - writer.insert( Position.createAt( editable1 ), writer.createText( 'First editable.' ) ); - writer.insert( Position.createAt( editable2 ), writer.createText( 'Second editable.' ) ); + writer.insert( writer.createPositionAt( editable1 ), writer.createText( 'First editable.' ) ); + writer.insert( writer.createPositionAt( editable2 ), writer.createText( 'Second editable.' ) ); writer.setSelection( editable1 ); } ); diff --git a/tests/view/manual/keyobserver.js b/tests/view/manual/keyobserver.js index a2d7706c0..713fad3f2 100644 --- a/tests/view/manual/keyobserver.js +++ b/tests/view/manual/keyobserver.js @@ -6,7 +6,6 @@ /* globals console, document */ import View from '../../../src/view/view'; -import Position from '../../../src/view/position'; import createViewRoot from '../_utils/createroot'; const view = new View(); @@ -20,7 +19,7 @@ view.attachDomRoot( document.getElementById( 'editable' ), 'editable' ); view.change( writer => { const text = writer.createText( 'foobar' ); - writer.insert( Position.createAt( viewRoot ), text ); + writer.insert( writer.createPositionAt( viewRoot ), text ); writer.setSelection( text, 3 ); } ); diff --git a/tests/view/observer/selectionobserver.js b/tests/view/observer/selectionobserver.js index 6d2d2c909..ae97829bf 100644 --- a/tests/view/observer/selectionobserver.js +++ b/tests/view/observer/selectionobserver.js @@ -107,7 +107,7 @@ describe( 'SelectionObserver', () => { const viewBar = viewDocument.getRoot().getChild( 1 ).getChild( 0 ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( viewBar, 1, viewBar, 2 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( viewBar, 1, viewBar, 2 ) ); } ); } ); @@ -192,7 +192,7 @@ describe( 'SelectionObserver', () => { it( 'should not be treated as an infinite loop if selection is changed only few times', done => { const viewFoo = viewDocument.getRoot().getChild( 0 ).getChild( 0 ); - viewDocument.selection._setTo( ViewRange.createFromParentsAndOffsets( viewFoo, 0, viewFoo, 0 ) ); + viewDocument.selection._setTo( ViewRange._createFromParentsAndOffsets( viewFoo, 0, viewFoo, 0 ) ); const spy = testUtils.sinon.spy( log, 'warn' ); viewDocument.on( 'selectionChangeDone', () => { diff --git a/tests/view/placeholder.js b/tests/view/placeholder.js index 06b3f600f..e8a2bfdcc 100644 --- a/tests/view/placeholder.js +++ b/tests/view/placeholder.js @@ -98,7 +98,7 @@ describe( 'placeholder', () => { expect( element.hasClass( 'ck-placeholder' ) ).to.be.true; view.change( writer => { - writer.setSelection( ViewRange.createIn( element ) ); + writer.setSelection( ViewRange._createIn( element ) ); } ); expect( element.hasClass( 'ck-placeholder' ) ).to.be.false; @@ -147,11 +147,11 @@ describe( 'placeholder', () => { // Move selection to the elements with placeholders. view.change( writer => { - writer.setSelection( ViewRange.createIn( element ) ); + writer.setSelection( ViewRange._createIn( element ) ); } ); secondView.change( writer => { - writer.setSelection( ViewRange.createIn( secondElement ) ); + writer.setSelection( ViewRange._createIn( secondElement ) ); } ); expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'first placeholder' ); @@ -168,7 +168,7 @@ describe( 'placeholder', () => { attachPlaceholder( view, element, 'foo bar baz' ); view.change( writer => { - writer.setSelection( ViewRange.createIn( element ) ); + writer.setSelection( ViewRange._createIn( element ) ); // Here we are before rendering - placeholder is visible in first element; expect( element.getAttribute( 'data-placeholder' ) ).to.equal( 'foo bar baz' ); diff --git a/tests/view/position.js b/tests/view/position.js index 70785c04e..f71c41c2a 100644 --- a/tests/view/position.js +++ b/tests/view/position.js @@ -15,6 +15,10 @@ import TextProxy from '../../src/view/textproxy'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import { parse, stringify } from '../../src/dev-utils/view'; +import TreeWalker from '../../src/view/treewalker'; +import createViewRoot from './_utils/createroot'; +import AttributeElement from '../../src/view/attributeelement'; +import ContainerElement from '../../src/view/containerelement'; describe( 'Position', () => { const parentMock = {}; @@ -151,88 +155,6 @@ describe( 'Position', () => { } ); } ); - describe( 'createAt', () => { - it( 'should throw if no offset is passed', () => { - const element = new Element( 'p' ); - - expect( () => Position.createAt( element ) ).to.throw( CKEditorError, /view-position-createAt-offset-required/ ); - } ); - - it( 'should create positions from positions', () => { - const spy = sinon.spy( Position, 'createFromPosition' ); - - const p = new Element( 'p' ); - const position = new Position( p, 0 ); - const created = Position.createAt( position, 0 ); - - expect( created.isEqual( position ) ).to.be.true; - expect( spy.calledOnce ).to.be.true; - } ); - - it( 'should create positions from node and offset', () => { - const foo = new Text( 'foo' ); - const p = new Element( 'p', null, foo ); - - expect( Position.createAt( foo, 0 ).parent ).to.equal( foo ); - expect( Position.createAt( foo, 0 ).offset ).to.equal( 0 ); - - expect( Position.createAt( foo, 2 ).parent ).to.equal( foo ); - expect( Position.createAt( foo, 2 ).offset ).to.equal( 2 ); - - expect( Position.createAt( p, 1 ).parent ).to.equal( p ); - expect( Position.createAt( p, 1 ).offset ).to.equal( 1 ); - } ); - - it( 'should create positions from node and flag', () => { - const foo = new Text( 'foo' ); - const p = new Element( 'p', null, foo ); - - const fooEnd = Position.createAt( foo, 'end' ); - const fooBefore = Position.createAt( foo, 'before' ); - const fooAfter = Position.createAt( foo, 'after' ); - - const pEnd = Position.createAt( p, 'end' ); - // pBefore and pAfter would throw. - - expect( fooEnd.parent ).to.equal( foo ); - expect( fooEnd.offset ).to.equal( 3 ); - - expect( fooBefore.parent ).to.equal( p ); - expect( fooBefore.offset ).to.equal( 0 ); - - expect( fooAfter.parent ).to.equal( p ); - expect( fooAfter.offset ).to.equal( 1 ); - - expect( pEnd.parent ).to.equal( p ); - expect( pEnd.offset ).to.equal( 1 ); - } ); - - it( 'should create positions in document fragment', () => { - const foo = new Text( 'foo' ); - const docFrag = new DocumentFragment( [ foo ] ); - - const pStart = Position.createAt( docFrag, 0 ); - const pEnd = Position.createAt( docFrag, 'end' ); - - expect( pStart.parent ).to.equal( docFrag ); - expect( pStart.offset ).to.equal( 0 ); - expect( pEnd.parent ).to.equal( docFrag ); - expect( pEnd.offset ).to.equal( 1 ); - } ); - } ); - - describe( 'createFromPosition', () => { - it( 'creates new Position with same parent and offset', () => { - const offset = 50; - const position = new Position( parentMock, offset ); - const newPosition = Position.createFromPosition( position ); - - expect( position ).to.not.equal( newPosition ); - expect( position.offset ).to.equal( offset ); - expect( position.parent ).to.equal( parentMock ); - } ); - } ); - describe( 'isEqual', () => { it( 'should return true for same object', () => { const position = new Position( {}, 12 ); @@ -456,53 +378,123 @@ describe( 'Position', () => { } ); } ); - describe( 'createBefore', () => { - it( 'should throw error if one try to create positions before root', () => { - expect( () => { - Position.createBefore( parse( '

' ) ); - } ).to.throw( CKEditorError, /view-position-before-root/ ); - } ); + describe( 'static creators', () => { + describe( '_createAt()', () => { + it( 'should throw if no offset is passed', () => { + const element = new Element( 'p' ); - it( 'should create positions before `Node`', () => { - const { selection } = parse( '

[]

' ); - const position = selection.getFirstPosition(); - const nodeAfter = position.nodeAfter; + expect( () => Position._createAt( element ) ).to.throw( CKEditorError, /view-createPositionAt-offset-required/ ); + } ); - expect( Position.createBefore( nodeAfter ).isEqual( position ) ).to.be.true; - } ); + it( 'should create positions from positions', () => { + const p = new Element( 'p' ); + const position = new Position( p, 0 ); + const created = Position._createAt( position, 0 ); - it( 'should create positions before `TextProxy`', () => { - const text = new Text( 'abc' ); + expect( created.isEqual( position ) ).to.be.true; + expect( created ).to.not.be.equal( position ); + } ); - const textProxy = new TextProxy( text, 1, 1 ); - const position = new Position( text, 1 ); + it( 'should create positions from node and offset', () => { + const foo = new Text( 'foo' ); + const p = new Element( 'p', null, foo ); - expect( Position.createBefore( textProxy ) ).deep.equal( position ); - } ); - } ); + expect( Position._createAt( foo, 0 ).parent ).to.equal( foo ); + expect( Position._createAt( foo, 0 ).offset ).to.equal( 0 ); + + expect( Position._createAt( foo, 2 ).parent ).to.equal( foo ); + expect( Position._createAt( foo, 2 ).offset ).to.equal( 2 ); + + expect( Position._createAt( p, 1 ).parent ).to.equal( p ); + expect( Position._createAt( p, 1 ).offset ).to.equal( 1 ); + } ); + + it( 'should create positions from node and flag', () => { + const foo = new Text( 'foo' ); + const p = new Element( 'p', null, foo ); + + const fooEnd = Position._createAt( foo, 'end' ); + const fooBefore = Position._createAt( foo, 'before' ); + const fooAfter = Position._createAt( foo, 'after' ); + + const pEnd = Position._createAt( p, 'end' ); + // pBefore and pAfter would throw. + + expect( fooEnd.parent ).to.equal( foo ); + expect( fooEnd.offset ).to.equal( 3 ); + + expect( fooBefore.parent ).to.equal( p ); + expect( fooBefore.offset ).to.equal( 0 ); + + expect( fooAfter.parent ).to.equal( p ); + expect( fooAfter.offset ).to.equal( 1 ); + + expect( pEnd.parent ).to.equal( p ); + expect( pEnd.offset ).to.equal( 1 ); + } ); - describe( 'createAfter', () => { - it( 'should throw error if one try to create positions after root', () => { - expect( () => { - Position.createAfter( parse( '

' ) ); - } ).to.throw( CKEditorError, /view-position-after-root/ ); + it( 'should create positions in document fragment', () => { + const foo = new Text( 'foo' ); + const docFrag = new DocumentFragment( [ foo ] ); + + const pStart = Position._createAt( docFrag, 0 ); + const pEnd = Position._createAt( docFrag, 'end' ); + + expect( pStart.parent ).to.equal( docFrag ); + expect( pStart.offset ).to.equal( 0 ); + expect( pEnd.parent ).to.equal( docFrag ); + expect( pEnd.offset ).to.equal( 1 ); + } ); } ); - it( 'should create positions after `Node`', () => { - const { selection } = parse( '

[]

' ); - const position = selection.getFirstPosition(); - const nodeBefore = position.nodeBefore; + describe( '_createBefore()', () => { + it( 'should throw error if one try to create positions before root', () => { + expect( () => { + Position._createBefore( parse( '

' ) ); + } ).to.throw( CKEditorError, /view-position-before-root/ ); + } ); + + it( 'should create positions before `Node`', () => { + const { selection } = parse( '

[]

' ); + const position = selection.getFirstPosition(); + const nodeAfter = position.nodeAfter; + + expect( Position._createBefore( nodeAfter ).isEqual( position ) ).to.be.true; + } ); + + it( 'should create positions before `TextProxy`', () => { + const text = new Text( 'abc' ); - expect( Position.createAfter( nodeBefore ).isEqual( position ) ).to.be.true; + const textProxy = new TextProxy( text, 1, 1 ); + const position = new Position( text, 1 ); + + expect( Position._createBefore( textProxy ) ).deep.equal( position ); + } ); } ); - it( 'should create positions after `TextProxy`', () => { - const text = new Text( 'abcd' ); + describe( '_createAfter()', () => { + it( 'should throw error if one try to create positions after root', () => { + expect( () => { + Position._createAfter( parse( '

' ) ); + } ).to.throw( CKEditorError, /view-position-after-root/ ); + } ); - const textProxy = new TextProxy( text, 1, 2 ); - const position = new Position( text, 3 ); + it( 'should create positions after `Node`', () => { + const { selection } = parse( '

[]

' ); + const position = selection.getFirstPosition(); + const nodeBefore = position.nodeBefore; + + expect( Position._createAfter( nodeBefore ).isEqual( position ) ).to.be.true; + } ); + + it( 'should create positions after `TextProxy`', () => { + const text = new Text( 'abcd' ); + + const textProxy = new TextProxy( text, 1, 2 ); + const position = new Position( text, 3 ); - expect( Position.createAfter( textProxy ) ).deep.equal( position ); + expect( Position._createAfter( textProxy ) ).deep.equal( position ); + } ); } ); } ); @@ -572,13 +564,13 @@ describe( 'Position', () => { it( 'for two the same positions returns the parent element', () => { const afterLoremPosition = new Position( liOl1, 5 ); - const otherPosition = Position.createFromPosition( afterLoremPosition ); + const otherPosition = Position._createAt( afterLoremPosition ); test( afterLoremPosition, otherPosition, liOl1 ); } ); it( 'for two positions in the same element returns the element', () => { - const startMaecenasPosition = Position.createAt( liOl2, 0 ); + const startMaecenasPosition = Position._createAt( liOl2, 0 ); const beforeTellusPosition = new Position( liOl2, 18 ); test( startMaecenasPosition, beforeTellusPosition, liOl2 ); @@ -611,4 +603,54 @@ describe( 'Position', () => { expect( positionB.getCommonAncestor( positionA ) ).to.equal( lca ); } } ); + + describe( 'getWalker()', () => { + let root; + + beforeEach( () => { + const doc = new Document(); + + root = createViewRoot( doc ); + + const textAbcd = new Text( 'abcd' ); + const bold = new AttributeElement( 'b', null, [ textAbcd ] ); + + const paragraph = new ContainerElement( 'p', null, [ bold ] ); + const img = new ContainerElement( 'img' ); + + root._insertChild( 0, [ img, paragraph ] ); + } ); + + it( 'should be possible to iterate using this method', () => { + const position = new Position( root, 0 ); + + const items = []; + const walker = position.getWalker(); + + for ( const value of walker ) { + items.push( value.type + ':' + ( value.item.name || value.item.data ) ); + } + + expect( items ).to.deep.equal( [ + 'elementStart:img', + 'elementEnd:img', + 'elementStart:p', + 'elementStart:b', + 'text:abcd', + 'elementEnd:b', + 'elementEnd:p' + ] ); + } ); + + it( 'should return treewalker with given options', () => { + const position = new Position( root, 0 ); + const walker = position.getWalker( { singleCharacters: true } ); + + expect( walker ).to.be.instanceof( TreeWalker ); + expect( walker ).to.have.property( 'singleCharacters' ).that.is.true; + expect( walker ).to.have.property( 'position' ); + expect( walker.position.isEqual( position ) ).to.be.true; + expect( walker ).to.have.property( 'shallow' ).that.is.false; + } ); + } ); } ); diff --git a/tests/view/range.js b/tests/view/range.js index b58a9208c..6b82d4bfe 100644 --- a/tests/view/range.js +++ b/tests/view/range.js @@ -318,7 +318,7 @@ describe( 'Range', () => { } ); it( 'should return false if ranges are equal', () => { - const otherRange = Range.createFromRange( range ); + const otherRange = range.clone(); expect( range.containsRange( otherRange ) ).to.be.false; } ); @@ -330,7 +330,7 @@ describe( 'Range', () => { } ); it( 'should return true if ranges are equal and check is not strict', () => { - const otherRange = Range.createFromRange( range ); + const otherRange = range.clone(); expect( range.containsRange( otherRange, true ) ).to.be.true; } ); @@ -377,47 +377,47 @@ describe( 'Range', () => { describe( 'isIntersecting', () => { it( 'should return true if given range is equal', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t3, 2 ); - const otherRange = Range.createFromRange( range ); + const range = Range._createFromParentsAndOffsets( t1, 0, t3, 2 ); + const otherRange = range.clone(); expect( range.isIntersecting( otherRange ) ).to.be.true; expect( otherRange.isIntersecting( range ) ).to.be.true; } ); it( 'should return true if given range contains this range', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t3, 3 ); - const otherRange = Range.createFromParentsAndOffsets( p1, 1, t2, 2 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t3, 3 ); + const otherRange = Range._createFromParentsAndOffsets( p1, 1, t2, 2 ); expect( range.isIntersecting( otherRange ) ).to.be.true; expect( otherRange.isIntersecting( range ) ).to.be.true; } ); it( 'should return true if given range ends in this range', () => { - const range = Range.createFromParentsAndOffsets( root, 1, t3, 3 ); - const otherRange = Range.createFromParentsAndOffsets( t1, 0, p2, 0 ); + const range = Range._createFromParentsAndOffsets( root, 1, t3, 3 ); + const otherRange = Range._createFromParentsAndOffsets( t1, 0, p2, 0 ); expect( range.isIntersecting( otherRange ) ).to.be.true; expect( otherRange.isIntersecting( range ) ).to.be.true; } ); it( 'should return true if given range starts in this range', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t2, 3 ); - const otherRange = Range.createFromParentsAndOffsets( p1, 1, p2, 0 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t2, 3 ); + const otherRange = Range._createFromParentsAndOffsets( p1, 1, p2, 0 ); expect( range.isIntersecting( otherRange ) ).to.be.true; expect( otherRange.isIntersecting( range ) ).to.be.true; } ); it( 'should return false if given range is fully before/after this range', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t2, 3 ); - const otherRange = Range.createFromParentsAndOffsets( root, 1, t3, 0 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t2, 3 ); + const otherRange = Range._createFromParentsAndOffsets( root, 1, t3, 0 ); expect( range.isIntersecting( otherRange ) ).to.be.false; expect( otherRange.isIntersecting( range ) ).to.be.false; } ); it( 'should return false if ranges are in different roots', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t2, 3 ); - const otherRange = Range.createFromParentsAndOffsets( new Element( 'div' ), 1, t3, 0 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t2, 3 ); + const otherRange = Range._createFromParentsAndOffsets( new Element( 'div' ), 1, t3, 0 ); expect( range.isIntersecting( otherRange ) ).to.be.false; expect( otherRange.isIntersecting( range ) ).to.be.false; @@ -426,8 +426,8 @@ describe( 'Range', () => { describe( 'getDifference', () => { it( 'should return range equal to original range if other range does not intersect with it', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t2, 3 ); - const otherRange = Range.createFromParentsAndOffsets( root, 1, t3, 0 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t2, 3 ); + const otherRange = Range._createFromParentsAndOffsets( root, 1, t3, 0 ); const difference = range.getDifference( otherRange ); expect( difference.length ).to.equal( 1 ); @@ -435,8 +435,8 @@ describe( 'Range', () => { } ); it( 'should return shrunken range if other range intersects with it', () => { - const range = Range.createFromParentsAndOffsets( root, 1, t3, 3 ); - const otherRange = Range.createFromParentsAndOffsets( t1, 0, p2, 0 ); + const range = Range._createFromParentsAndOffsets( root, 1, t3, 3 ); + const otherRange = Range._createFromParentsAndOffsets( t1, 0, p2, 0 ); const difference = range.getDifference( otherRange ); expect( difference.length ).to.equal( 1 ); @@ -448,16 +448,16 @@ describe( 'Range', () => { } ); it( 'should return an empty array if other range contains or is same as the original range', () => { - const range = Range.createFromParentsAndOffsets( p1, 1, t2, 2 ); - const otherRange = Range.createFromParentsAndOffsets( t1, 0, t3, 3 ); + const range = Range._createFromParentsAndOffsets( p1, 1, t2, 2 ); + const otherRange = Range._createFromParentsAndOffsets( t1, 0, t3, 3 ); const difference = range.getDifference( otherRange ); expect( difference.length ).to.equal( 0 ); } ); it( 'should two ranges if other range is contained by the original range', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t3, 3 ); - const otherRange = Range.createFromParentsAndOffsets( p1, 1, t2, 2 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t3, 3 ); + const otherRange = Range._createFromParentsAndOffsets( p1, 1, t2, 2 ); const difference = range.getDifference( otherRange ); expect( difference.length ).to.equal( 2 ); @@ -476,32 +476,32 @@ describe( 'Range', () => { describe( 'getIntersection', () => { it( 'should return range equal to original range if other range contains it', () => { - const range = Range.createFromParentsAndOffsets( t2, 0, t3, 0 ); - const otherRange = Range.createFromParentsAndOffsets( t1, 1, t3, 1 ); + const range = Range._createFromParentsAndOffsets( t2, 0, t3, 0 ); + const otherRange = Range._createFromParentsAndOffsets( t1, 1, t3, 1 ); const intersection = range.getIntersection( otherRange ); expect( intersection.isEqual( range ) ).to.be.true; } ); it( 'should return range equal to other range if it is contained in original range', () => { - const range = Range.createFromParentsAndOffsets( t1, 1, t3, 1 ); - const otherRange = Range.createFromParentsAndOffsets( t2, 0, t3, 0 ); + const range = Range._createFromParentsAndOffsets( t1, 1, t3, 1 ); + const otherRange = Range._createFromParentsAndOffsets( t2, 0, t3, 0 ); const intersection = range.getIntersection( otherRange ); expect( intersection.isEqual( otherRange ) ).to.be.true; } ); it( 'should return null if ranges do not intersect', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t2, 3 ); - const otherRange = Range.createFromParentsAndOffsets( t3, 0, t3, 3 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t2, 3 ); + const otherRange = Range._createFromParentsAndOffsets( t3, 0, t3, 3 ); const intersection = range.getIntersection( otherRange ); expect( intersection ).to.be.null; } ); it( 'should return common part if ranges intersect partially', () => { - const range = Range.createFromParentsAndOffsets( t1, 0, t2, 3 ); - const otherRange = Range.createFromParentsAndOffsets( t2, 0, t3, 3 ); + const range = Range._createFromParentsAndOffsets( t1, 0, t2, 3 ); + const otherRange = Range._createFromParentsAndOffsets( t2, 0, t3, 3 ); const intersection = range.getIntersection( otherRange ); expect( intersection.start.parent ).to.equal( t2 ); @@ -654,9 +654,9 @@ describe( 'Range', () => { div = new Element( 'div', null, p ); } ); - describe( 'createIn', () => { + describe( '_createIn', () => { it( 'should return range', () => { - const range = Range.createIn( p ); + const range = Range._createIn( p ); expect( range.start.parent ).to.deep.equal( p ); expect( range.start.offset ).to.deep.equal( 0 ); @@ -665,9 +665,9 @@ describe( 'Range', () => { } ); } ); - describe( 'createOn', () => { + describe( '_createOn', () => { it( 'should return range', () => { - const range = Range.createOn( p ); + const range = Range._createOn( p ); expect( range.start.parent ).to.equal( div ); expect( range.start.offset ).to.equal( 0 ); @@ -678,7 +678,7 @@ describe( 'Range', () => { it( 'should create a proper range on a text proxy', () => { const text = new Text( 'foobar' ); const textProxy = new TextProxy( text, 2, 3 ); - const range = Range.createOn( textProxy ); + const range = Range._createOn( textProxy ); expect( range.start.parent ).to.equal( text ); expect( range.start.offset ).to.equal( 2 ); @@ -687,31 +687,9 @@ describe( 'Range', () => { } ); } ); - describe( 'createCollapsedAt()', () => { - it( 'should return new collapsed range at the given item position', () => { - const item = new Element( 'p', null, new Text( 'foo' ) ); - const range = Range.createCollapsedAt( item, 0 ); - - expect( range.start.parent ).to.equal( item ); - expect( range.start.offset ).to.equal( 0 ); - - expect( range.isCollapsed ).to.be.true; - } ); - - it( 'should return new collapse range at the given item position and offset', () => { - const item = new Element( 'p', null, new Text( 'foo' ) ); - const range = Range.createCollapsedAt( item, 1 ); - - expect( range.start.parent ).to.equal( item ); - expect( range.start.offset ).to.equal( 1 ); - - expect( range.isCollapsed ).to.be.true; - } ); - } ); - - describe( 'createFromParentsAndOffsets', () => { + describe( '_createFromParentsAndOffsets', () => { it( 'should return range', () => { - const range = Range.createFromParentsAndOffsets( div, 0, foz, 1 ); + const range = Range._createFromParentsAndOffsets( div, 0, foz, 1 ); expect( range.start.parent ).to.deep.equal( div ); expect( range.start.offset ).to.deep.equal( 0 ); @@ -720,10 +698,10 @@ describe( 'Range', () => { } ); } ); - describe( 'createFromPositionAndShift', () => { + describe( '_createFromPositionAndShift', () => { it( 'should make range from start position and offset', () => { const position = new Position( foz, 1 ); - const range = Range.createFromPositionAndShift( position, 2 ); + const range = Range._createFromPositionAndShift( position, 2 ); expect( range ).to.be.instanceof( Range ); expect( range.start.isEqual( position ) ).to.be.true; @@ -733,7 +711,7 @@ describe( 'Range', () => { it( 'should accept negative shift value', () => { const position = new Position( foz, 3 ); - const range = Range.createFromPositionAndShift( position, -1 ); + const range = Range._createFromPositionAndShift( position, -1 ); expect( range ).to.be.instanceof( Range ); expect( range.end.isEqual( position ) ).to.be.true; @@ -741,16 +719,6 @@ describe( 'Range', () => { expect( range.start.offset ).to.deep.equal( 2 ); } ); } ); - - describe( 'createFromRange', () => { - it( 'should create a new instance of Range that is equal to passed range', () => { - const range = new Range( new Position( foz, 0 ), new Position( foz, 2 ) ); - const clone = Range.createFromRange( range ); - - expect( clone ).not.to.be.equal( range ); // clone is not pointing to the same object as position - expect( clone.isEqual( range ) ).to.be.true; // but they are equal in the position-sense - } ); - } ); } ); describe( 'getCommonAncestor()', () => { diff --git a/tests/view/renderer.js b/tests/view/renderer.js index 4dd9a2455..eae35af83 100644 --- a/tests/view/renderer.js +++ b/tests/view/renderer.js @@ -519,7 +519,7 @@ describe( 'Renderer', () => { renderAndExpectNoChanges( renderer, domRoot ); // Step 3:

foo{}

- selection._setTo( ViewRange.createFromParentsAndOffsets( viewP.getChild( 0 ), 3, viewP.getChild( 0 ), 3 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewP.getChild( 0 ), 3, viewP.getChild( 0 ), 3 ) ); renderer.render(); @@ -572,7 +572,7 @@ describe( 'Renderer', () => { renderAndExpectNoChanges( renderer, domRoot ); // Step 3:

{}foo

- selection._setTo( ViewRange.createFromParentsAndOffsets( + selection._setTo( ViewRange._createFromParentsAndOffsets( viewP.getChild( 0 ).getChild( 0 ), 0, viewP.getChild( 0 ).getChild( 0 ), 0 ) ); renderer.render(); @@ -623,7 +623,7 @@ describe( 'Renderer', () => { renderAndExpectNoChanges( renderer, domRoot ); // Step 3:

foo{}

- selection._setTo( ViewRange.createFromParentsAndOffsets( + selection._setTo( ViewRange._createFromParentsAndOffsets( viewP.getChild( 0 ).getChild( 0 ), 3, viewP.getChild( 0 ).getChild( 0 ), 3 ) ); renderer.render(); @@ -696,7 +696,7 @@ describe( 'Renderer', () => { // Step 2:

foo"FILLER{}"

const viewI = viewP.getChild( 2 ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewI, 0, viewI, 0 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewI, 0, viewI, 0 ) ); renderer.render(); @@ -729,7 +729,7 @@ describe( 'Renderer', () => { // Step 2: Add text node. const viewText = new ViewText( 'x' ); viewB._appendChild( viewText ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); renderer.markToSync( 'children', viewB ); renderer.render(); @@ -765,7 +765,7 @@ describe( 'Renderer', () => { // Step 2: Remove the and update the selection (

bar[]

). viewP._removeChildren( 1 ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewP, 1, viewP, 1 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewP, 1, viewP, 1 ) ); renderer.markToSync( 'children', viewP ); renderer.render(); @@ -802,7 +802,7 @@ describe( 'Renderer', () => { viewP2._appendChild( removedChildren ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewP, 0, viewP, 0 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewP, 0, viewP, 0 ) ); renderer.markToSync( 'children', viewP ); renderer.markToSync( 'children', viewP2 ); @@ -839,7 +839,7 @@ describe( 'Renderer', () => { const viewI = parse( '' ); viewP._appendChild( viewI ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewI, 0, viewI, 0 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewI, 0, viewI, 0 ) ); renderer.markToSync( 'children', viewP ); renderer.render(); @@ -869,7 +869,7 @@ describe( 'Renderer', () => { const viewAbc = parse( 'abc' ); viewP._appendChild( viewAbc ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewP, 3, viewP, 3 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewP, 3, viewP, 3 ) ); renderer.markToSync( 'children', viewP ); renderer.render(); @@ -912,7 +912,7 @@ describe( 'Renderer', () => { const viewText = new ViewText( 'x' ); viewP._appendChild( viewText ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); renderer.markToSync( 'children', viewP ); renderAndExpectNoChanges( renderer, domRoot ); @@ -942,7 +942,7 @@ describe( 'Renderer', () => { // Add text node only in View

x{}

const viewText = new ViewText( 'x' ); viewP._appendChild( viewText ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); renderer.markToSync( 'children', viewP ); renderer.render(); @@ -989,7 +989,7 @@ describe( 'Renderer', () => { viewP._removeChildren( 0 ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewP, 0, viewP, 0 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewP, 0, viewP, 0 ) ); renderer.markToSync( 'children', viewP ); renderAndExpectNoChanges( renderer, domRoot ); @@ -1040,7 +1040,7 @@ describe( 'Renderer', () => { const viewText = new ViewText( 'x' ); viewB._appendChild( viewText ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); renderer.markToSync( 'children', viewP ); renderAndExpectNoChanges( renderer, domRoot ); @@ -1083,7 +1083,7 @@ describe( 'Renderer', () => { const viewText = new ViewText( 'x' ); viewB._appendChild( viewText ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); renderer.markToSync( 'children', viewB ); renderer.render(); @@ -1146,7 +1146,7 @@ describe( 'Renderer', () => { const viewText = new ViewText( 'x' ); viewB._appendChild( viewText ); - selection._setTo( ViewRange.createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); + selection._setTo( ViewRange._createFromParentsAndOffsets( viewText, 1, viewText, 1 ) ); renderer.markToSync( 'text', viewText ); renderer.render(); @@ -3281,7 +3281,7 @@ describe( 'Renderer', () => { textNode._data = 'foobar'; view.change( writer => { - writer.insert( ViewPosition.createAfter( textNode ), new ViewAttributeElement( 'img' ) ); + writer.insert( ViewPosition._createAfter( textNode ), new ViewAttributeElement( 'img' ) ); } ); expect( getViewData( view ) ).to.equal( '

foobar

' ); @@ -3307,7 +3307,7 @@ describe( 'Renderer', () => { textNode._data = 'foobar'; view.change( writer => { - writer.insert( ViewPosition.createBefore( textNode ), new ViewAttributeElement( 'img' ) ); + writer.insert( ViewPosition._createBefore( textNode ), new ViewAttributeElement( 'img' ) ); } ); expect( getViewData( view ) ).to.equal( '

foobar

' ); @@ -3337,7 +3337,7 @@ describe( 'Renderer', () => { const firstElement = container.getChild( 0 ); view.change( writer => { - writer.remove( ViewRange.createOn( firstElement ) ); + writer.remove( ViewRange._createOn( firstElement ) ); writer.insert( new ViewPosition( container, 2 ), firstElement ); } ); diff --git a/tests/view/rooteditableelement.js b/tests/view/rooteditableelement.js index 6ebd870e1..e43189bd5 100644 --- a/tests/view/rooteditableelement.js +++ b/tests/view/rooteditableelement.js @@ -45,11 +45,13 @@ describe( 'RootEditableElement', () => { el = new RootEditableElement( 'div' ); } ); - it( 'should return true for rootElement/containerElement/element, also with correct name and element name', () => { + it( 'should return true for rootElement/containerElement/editable/element, also with correct name and element name', () => { expect( el.is( 'rootElement' ) ).to.be.true; expect( el.is( 'rootElement', 'div' ) ).to.be.true; expect( el.is( 'containerElement' ) ).to.be.true; expect( el.is( 'containerElement', 'div' ) ).to.be.true; + expect( el.is( 'editableElement' ) ).to.be.true; + expect( el.is( 'editableElement', 'div' ) ).to.be.true; expect( el.is( 'element' ) ).to.be.true; expect( el.is( 'element', 'div' ) ).to.be.true; expect( el.is( 'div' ) ).to.be.true; diff --git a/tests/view/selection.js b/tests/view/selection.js index 6c503e9d1..5eaca27ac 100644 --- a/tests/view/selection.js +++ b/tests/view/selection.js @@ -14,19 +14,22 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import count from '@ckeditor/ckeditor5-utils/src/count'; import createViewRoot from './_utils/createroot'; import { parse } from '../../src/dev-utils/view'; +import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; describe( 'Selection', () => { let selection, el, range1, range2, range3; + testUtils.createSinonSandbox(); + beforeEach( () => { const text = new Text( 'xxxxxxxxxxxxxxxxxxxx' ); el = new Element( 'p', null, text ); selection = new Selection(); - range1 = Range.createFromParentsAndOffsets( text, 5, text, 10 ); - range2 = Range.createFromParentsAndOffsets( text, 1, text, 2 ); - range3 = Range.createFromParentsAndOffsets( text, 12, text, 14 ); + range1 = Range._createFromParentsAndOffsets( text, 5, text, 10 ); + range2 = Range._createFromParentsAndOffsets( text, 1, text, 2 ); + range3 = Range._createFromParentsAndOffsets( text, 12, text, 14 ); } ); describe( 'constructor()', () => { @@ -118,7 +121,7 @@ describe( 'Selection', () => { it( 'should throw an error when ranges intersects', () => { const text = el.getChild( 0 ); - const range2 = Range.createFromParentsAndOffsets( text, 7, text, 15 ); + const range2 = Range._createFromParentsAndOffsets( text, 7, text, 15 ); expect( () => { // eslint-disable-next-line no-new @@ -198,7 +201,7 @@ describe( 'Selection', () => { } ); it( 'throws if there are no ranges in selection', () => { - const endPos = Position.createAt( el, 'end' ); + const endPos = Position._createAt( el, 'end' ); expect( () => { selection.setFocus( endPos ); @@ -206,8 +209,8 @@ describe( 'Selection', () => { } ); it( 'modifies existing collapsed selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); selection.setTo( startPos ); @@ -218,8 +221,8 @@ describe( 'Selection', () => { } ); it( 'makes existing collapsed selection a backward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 0 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 0 ); selection.setTo( startPos ); @@ -231,9 +234,9 @@ describe( 'Selection', () => { } ); it( 'modifies existing non-collapsed selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 3 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 3 ); selection.setTo( new Range( startPos, endPos ) ); @@ -244,9 +247,9 @@ describe( 'Selection', () => { } ); it( 'makes existing non-collapsed selection a backward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 0 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 0 ); selection.setTo( new Range( startPos, endPos ) ); @@ -258,9 +261,9 @@ describe( 'Selection', () => { } ); it( 'makes existing backward selection a forward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 3 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 3 ); selection.setTo( new Range( startPos, endPos ), { backward: true } ); @@ -272,9 +275,9 @@ describe( 'Selection', () => { } ); it( 'modifies existing backward selection', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 0 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); + const newEndPos = Position._createAt( el, 0 ); selection.setTo( new Range( startPos, endPos ), { backward: true } ); @@ -287,12 +290,12 @@ describe( 'Selection', () => { it( 'modifies only the last range', () => { // Offsets are chosen in this way that the order of adding ranges must count, not their document order. - const startPos1 = Position.createAt( el, 4 ); - const endPos1 = Position.createAt( el, 5 ); - const startPos2 = Position.createAt( el, 1 ); - const endPos2 = Position.createAt( el, 2 ); + const startPos1 = Position._createAt( el, 4 ); + const endPos1 = Position._createAt( el, 5 ); + const startPos2 = Position._createAt( el, 1 ); + const endPos2 = Position._createAt( el, 2 ); - const newEndPos = Position.createAt( el, 0 ); + const newEndPos = Position._createAt( el, 0 ); selection.setTo( [ new Range( startPos1, endPos1 ), @@ -313,8 +316,8 @@ describe( 'Selection', () => { } ); it( 'collapses the selection when extending to the anchor', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); + const startPos = Position._createAt( el, 1 ); + const endPos = Position._createAt( el, 2 ); selection.setTo( new Range( startPos, endPos ) ); @@ -323,42 +326,26 @@ describe( 'Selection', () => { expect( selection.focus.compareWith( startPos ) ).to.equal( 'same' ); expect( selection.isCollapsed ).to.be.true; } ); - - it( 'uses Position.createAt', () => { - const startPos = Position.createAt( el, 1 ); - const endPos = Position.createAt( el, 2 ); - const newEndPos = Position.createAt( el, 4 ); - - const spy = sinon.stub( Position, 'createAt' ).returns( newEndPos ); - - selection.setTo( new Range( startPos, endPos ) ); - selection.setFocus( el, 'end' ); - - expect( spy.calledOnce ).to.be.true; - expect( selection.focus.compareWith( newEndPos ) ).to.equal( 'same' ); - - Position.createAt.restore(); - } ); } ); describe( 'isCollapsed', () => { it( 'should return true when there is single collapsed range', () => { - const range = Range.createFromParentsAndOffsets( el, 5, el, 5 ); + const range = Range._createFromParentsAndOffsets( el, 5, el, 5 ); selection.setTo( range ); expect( selection.isCollapsed ).to.be.true; } ); it( 'should return false when there are multiple ranges', () => { - const range1 = Range.createFromParentsAndOffsets( el, 5, el, 5 ); - const range2 = Range.createFromParentsAndOffsets( el, 15, el, 15 ); + const range1 = Range._createFromParentsAndOffsets( el, 5, el, 5 ); + const range2 = Range._createFromParentsAndOffsets( el, 15, el, 15 ); selection.setTo( [ range1, range2 ] ); expect( selection.isCollapsed ).to.be.false; } ); it( 'should return false when there is not collapsed range', () => { - const range = Range.createFromParentsAndOffsets( el, 15, el, 16 ); + const range = Range._createFromParentsAndOffsets( el, 15, el, 16 ); selection.setTo( range ); expect( selection.isCollapsed ).to.be.false; @@ -381,8 +368,8 @@ describe( 'Selection', () => { describe( 'isBackward', () => { it( 'is defined by the last added range', () => { - const range1 = Range.createFromParentsAndOffsets( el, 5, el, 10 ); - const range2 = Range.createFromParentsAndOffsets( el, 15, el, 16 ); + const range1 = Range._createFromParentsAndOffsets( el, 5, el, 10 ); + const range2 = Range._createFromParentsAndOffsets( el, 15, el, 16 ); selection.setTo( range1, { backward: true } ); expect( selection ).to.have.property( 'isBackward', true ); @@ -392,7 +379,7 @@ describe( 'Selection', () => { } ); it( 'is false when last range is collapsed', () => { - const range = Range.createFromParentsAndOffsets( el, 5, el, 5 ); + const range = Range._createFromParentsAndOffsets( el, 5, el, 5 ); selection.setTo( range, { backward: true } ); @@ -595,10 +582,10 @@ describe( 'Selection', () => { const span2 = p2.getChild( 0 ); //

[{]}

[{xx}]

- const rangeA1 = Range.createFromParentsAndOffsets( p1, 0, span1, 0 ); - const rangeB1 = Range.createFromParentsAndOffsets( span1, 0, p1, 1 ); - const rangeA2 = Range.createFromParentsAndOffsets( p2, 0, p2, 1 ); - const rangeB2 = Range.createFromParentsAndOffsets( span2, 0, span2, 1 ); + const rangeA1 = Range._createFromParentsAndOffsets( p1, 0, span1, 0 ); + const rangeB1 = Range._createFromParentsAndOffsets( span1, 0, p1, 1 ); + const rangeA2 = Range._createFromParentsAndOffsets( p2, 0, p2, 1 ); + const rangeB2 = Range._createFromParentsAndOffsets( span2, 0, span2, 1 ); selection.setTo( [ rangeA1, rangeA2 ] ); @@ -883,7 +870,7 @@ describe( 'Selection', () => { it( 'should throw when range is intersecting with already added range', () => { const text = el.getChild( 0 ); - const range2 = Range.createFromParentsAndOffsets( text, 7, text, 15 ); + const range2 = Range._createFromParentsAndOffsets( text, 7, text, 15 ); expect( () => { selection.setTo( [ range1, range2 ] ); @@ -953,7 +940,7 @@ describe( 'Selection', () => { const element = new Element( 'p' ); root._appendChild( element ); - selection.setTo( Range.createFromParentsAndOffsets( element, 0, element, 0 ) ); + selection.setTo( Range._createFromParentsAndOffsets( element, 0, element, 0 ) ); expect( selection.editableElement ).to.equal( root ); } ); diff --git a/tests/view/treewalker.js b/tests/view/treewalker.js index 8219df7d0..91540b61f 100644 --- a/tests/view/treewalker.js +++ b/tests/view/treewalker.js @@ -265,7 +265,7 @@ describe( 'TreeWalker', () => { } ]; - range = Range.createFromParentsAndOffsets( root, 1, paragraph, 3 ); + range = Range._createFromParentsAndOffsets( root, 1, paragraph, 3 ); } ); it( 'should iterating over the range', () => { @@ -328,7 +328,7 @@ describe( 'TreeWalker', () => { } ]; - range = Range.createFromParentsAndOffsets( textAbcd, 1, paragraph, 3 ); + range = Range._createFromParentsAndOffsets( textAbcd, 1, paragraph, 3 ); } ); it( 'should return part of the text', () => { @@ -493,7 +493,7 @@ describe( 'TreeWalker', () => { } ]; - const range = Range.createFromParentsAndOffsets( bold, 1, paragraph, 3 ); + const range = Range._createFromParentsAndOffsets( bold, 1, paragraph, 3 ); const iterator = new TreeWalker( { boundaries: range, @@ -972,7 +972,7 @@ describe( 'TreeWalker', () => { it( 'should not return elementEnd for a text node when iteration begins at the end of that text node', () => { const iterator = new TreeWalker( { - startPosition: Position.createAt( textAbcd, 'end' ) + startPosition: Position._createAt( textAbcd, 'end' ) } ); const step = iterator.next(); @@ -983,7 +983,7 @@ describe( 'TreeWalker', () => { it( 'should not return elementStart for a text node when iteration begins at the start of that text node', () => { const iterator = new TreeWalker( { - startPosition: Position.createAt( textAbcd, 0 ), + startPosition: Position._createAt( textAbcd, 0 ), direction: 'backward' } ); @@ -1039,7 +1039,7 @@ describe( 'TreeWalker', () => { } ]; - const iterator = new TreeWalker( { boundaries: Range.createIn( docFrag ) } ); + const iterator = new TreeWalker( { boundaries: Range._createIn( docFrag ) } ); let i = 0; for ( const value of iterator ) { diff --git a/tests/view/upcastwriter.js b/tests/view/upcastwriter.js index 7cd3b5ceb..67a899536 100644 --- a/tests/view/upcastwriter.js +++ b/tests/view/upcastwriter.js @@ -6,6 +6,9 @@ import Element from '../../src/view/element'; import UpcastWriter from '../../src/view/upcastwriter'; import HtmlDataProcessor from '../../src/dataprocessor/htmldataprocessor'; +import ViewPosition from '../../src/view/position'; +import ViewRange from '../../src/view/range'; +import ViewSelection from '../../src/view/selection'; describe( 'UpcastWriter', () => { let writer, view, dataprocessor; @@ -478,4 +481,51 @@ describe( 'UpcastWriter', () => { expect( Array.from( el.getCustomProperties() ).length ).to.equal( 0 ); } ); } ); + + describe( 'createPositionAt()', () => { + it( 'should return instance of Position', () => { + const span = new Element( 'span' ); + expect( writer.createPositionAt( span, 0 ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createPositionAfter()', () => { + it( 'should return instance of Position', () => { + const span = new Element( 'span', undefined, new Element( 'span' ) ); + expect( writer.createPositionAfter( span.getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createPositionBefore()', () => { + it( 'should return instance of Position', () => { + const span = new Element( 'span', undefined, new Element( 'span' ) ); + expect( writer.createPositionBefore( span.getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createRange()', () => { + it( 'should return instance of Range', () => { + expect( writer.createRange( writer.createPositionAt( new Element( 'span' ), 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createRangeIn()', () => { + it( 'should return instance of Range', () => { + const span = new Element( 'span', undefined, new Element( 'span' ) ); + expect( writer.createRangeIn( span.getChild( 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createRangeOn()', () => { + it( 'should return instance of Range', () => { + const span = new Element( 'span', undefined, new Element( 'span' ) ); + expect( writer.createRangeOn( span.getChild( 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createSelection()', () => { + it( 'should return instance of Selection', () => { + expect( writer.createSelection() ).to.be.instanceof( ViewSelection ); + } ); + } ); } ); diff --git a/tests/view/view/jumpoveruielement.js b/tests/view/view/jumpoveruielement.js index 5674aed1f..9897302b3 100644 --- a/tests/view/view/jumpoveruielement.js +++ b/tests/view/view/jumpoveruielement.js @@ -92,7 +92,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( [ ViewRange.createFromParentsAndOffsets( bar, 0, bar, 0 ) ] ); + writer.setSelection( [ ViewRange._createFromParentsAndOffsets( bar, 0, bar, 0 ) ] ); } ); renderAndFireKeydownEvent( { keyCode: keyCodes.arrowleft } ); @@ -110,7 +110,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( [ ViewRange.createFromParentsAndOffsets( p, 1, p, 1 ) ] ); + writer.setSelection( [ ViewRange._createFromParentsAndOffsets( p, 1, p, 1 ) ] ); } ); renderAndFireKeydownEvent(); @@ -130,7 +130,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( [ ViewRange.createFromParentsAndOffsets( foo, 3, foo, 3 ) ] ); + writer.setSelection( [ ViewRange._createFromParentsAndOffsets( foo, 3, foo, 3 ) ] ); } ); renderAndFireKeydownEvent(); @@ -150,7 +150,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( [ ViewRange.createFromParentsAndOffsets( foo, 3, foo, 3 ) ] ); + writer.setSelection( [ ViewRange._createFromParentsAndOffsets( foo, 3, foo, 3 ) ] ); } ); renderAndFireKeydownEvent(); @@ -172,7 +172,7 @@ describe( 'View', () => { view.change( writer => { viewRoot._appendChild( p ); viewRoot._appendChild( div ); - writer.setSelection( [ ViewRange.createFromParentsAndOffsets( foo, 3, foo, 3 ) ] ); + writer.setSelection( [ ViewRange._createFromParentsAndOffsets( foo, 3, foo, 3 ) ] ); } ); renderAndFireKeydownEvent(); @@ -193,7 +193,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( foo, 3, foo, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( foo, 3, foo, 3 ) ); } ); renderAndFireKeydownEvent(); @@ -214,7 +214,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( b, 1, b, 1 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( b, 1, b, 1 ) ); } ); renderAndFireKeydownEvent(); @@ -245,7 +245,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( foo, 3, foo, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( foo, 3, foo, 3 ) ); } ); renderAndFireKeydownEvent(); @@ -275,7 +275,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( foo, 3, foo, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( foo, 3, foo, 3 ) ); } ); renderAndFireKeydownEvent(); @@ -306,7 +306,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( foo, 3, foo, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( foo, 3, foo, 3 ) ); } ); renderAndFireKeydownEvent( { shiftKey: true } ); @@ -385,7 +385,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( foo, 2, foo, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( foo, 2, foo, 3 ) ); } ); renderAndFireKeydownEvent( { shiftKey: true } ); @@ -413,7 +413,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( foo, 2, foo, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( foo, 2, foo, 3 ) ); } ); renderAndFireKeydownEvent( { shiftKey: true } ); @@ -442,7 +442,7 @@ describe( 'View', () => { viewRoot._appendChild( p ); view.change( writer => { - writer.setSelection( ViewRange.createFromParentsAndOffsets( foo, 2, foo, 3 ) ); + writer.setSelection( ViewRange._createFromParentsAndOffsets( foo, 2, foo, 3 ) ); } ); renderAndFireKeydownEvent( { shiftKey: true } ); diff --git a/tests/view/view/view.js b/tests/view/view/view.js index 57647ee1c..ce6e928dc 100644 --- a/tests/view/view/view.js +++ b/tests/view/view/view.js @@ -11,6 +11,7 @@ import CompositionObserver from '../../../src/view/observer/compositionobserver' import ViewRange from '../../../src/view/range'; import ViewElement from '../../../src/view/element'; import ViewPosition from '../../../src/view/position'; +import ViewSelection from '../../../src/view/selection'; import { isBlockFiller, BR_FILLER } from '../../../src/view/filler'; import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; import log from '@ckeditor/ckeditor5-utils/src/log'; @@ -250,7 +251,7 @@ describe( 'view', () => { it( 'scrolls to the first range in selection with an offset', () => { const root = createViewRoot( viewDocument, 'div', 'main' ); const stub = testUtils.sinon.stub( global.window, 'scrollTo' ); - const range = ViewRange.createIn( root ); + const range = ViewRange._createIn( root ); view.attachDomRoot( domRoot ); @@ -478,8 +479,8 @@ describe( 'view', () => { return element; } ); - writer.insert( ViewPosition.createAt( p, 0 ), ui ); - writer.insert( ViewPosition.createAt( viewRoot, 0 ), p ); + writer.insert( ViewPosition._createAt( p, 0 ), ui ); + writer.insert( ViewPosition._createAt( viewRoot, 0 ), p ); } ); expect( renderingCalled ).to.be.true; @@ -603,6 +604,69 @@ describe( 'view', () => { } ); } ); + describe( 'createPositionAt()', () => { + it( 'should return instance of Position', () => { + createViewRoot( viewDocument, 'div', 'main' ); + viewDocument.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( view.createPositionAt( viewDocument.getRoot(), 0 ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createPositionAfter()', () => { + it( 'should return instance of Position', () => { + createViewRoot( viewDocument, 'div', 'main' ); + viewDocument.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( view.createPositionAfter( viewDocument.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createPositionBefore()', () => { + it( 'should return instance of Position', () => { + createViewRoot( viewDocument, 'div', 'main' ); + viewDocument.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( view.createPositionBefore( viewDocument.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); + } ); + } ); + + describe( 'createRange()', () => { + it( 'should return instance of Range', () => { + createViewRoot( viewDocument, 'div', 'main' ); + viewDocument.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( view.createRange( view.createPositionAt( viewDocument.getRoot(), 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createRangeIn()', () => { + it( 'should return instance of Range', () => { + createViewRoot( viewDocument, 'div', 'main' ); + viewDocument.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( view.createRangeIn( viewDocument.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createRangeOn()', () => { + it( 'should return instance of Range', () => { + createViewRoot( viewDocument, 'div', 'main' ); + viewDocument.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( view.createRangeOn( viewDocument.getRoot().getChild( 0 ) ) ).to.be.instanceof( ViewRange ); + } ); + } ); + + describe( 'createSelection()', () => { + it( 'should return instance of Selection', () => { + createViewRoot( viewDocument, 'div', 'main' ); + viewDocument.getRoot()._appendChild( new ViewElement( 'p' ) ); + + expect( view.createSelection() ).to.be.instanceof( ViewSelection ); + } ); + } ); + describe( 'destroy()', () => { it( 'should destroy all observers', () => { const observerMock = view.addObserver( ObserverMock );