Socket
Socket
Sign inDemoInstall

@ckeditor/ckeditor5-engine

Package Overview
Dependencies
Maintainers
1
Versions
618
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ckeditor/ckeditor5-engine - npm Package Compare versions

Comparing version 11.0.0 to 12.0.0

30

package.json
{
"name": "@ckeditor/ckeditor5-engine",
"version": "11.0.0",
"version": "12.0.0",
"description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.",

@@ -24,19 +24,19 @@ "keywords": [

"dependencies": {
"@ckeditor/ckeditor5-utils": "^11.0.0",
"@ckeditor/ckeditor5-utils": "^11.1.0",
"lodash-es": "^4.17.10"
},
"devDependencies": {
"@ckeditor/ckeditor5-basic-styles": "^10.0.3",
"@ckeditor/ckeditor5-block-quote": "^10.1.0",
"@ckeditor/ckeditor5-core": "^11.0.1",
"@ckeditor/ckeditor5-editor-classic": "^11.0.1",
"@ckeditor/ckeditor5-enter": "^10.1.2",
"@ckeditor/ckeditor5-essentials": "^10.1.2",
"@ckeditor/ckeditor5-heading": "^10.1.0",
"@ckeditor/ckeditor5-link": "^10.0.4",
"@ckeditor/ckeditor5-list": "^11.0.2",
"@ckeditor/ckeditor5-paragraph": "^10.0.3",
"@ckeditor/ckeditor5-typing": "^11.0.1",
"@ckeditor/ckeditor5-undo": "^10.0.3",
"@ckeditor/ckeditor5-widget": "^10.3.0",
"@ckeditor/ckeditor5-basic-styles": "^10.1.0",
"@ckeditor/ckeditor5-block-quote": "^10.1.1",
"@ckeditor/ckeditor5-core": "^11.1.0",
"@ckeditor/ckeditor5-editor-classic": "^11.0.2",
"@ckeditor/ckeditor5-enter": "^10.1.3",
"@ckeditor/ckeditor5-essentials": "^10.1.3",
"@ckeditor/ckeditor5-heading": "^10.1.1",
"@ckeditor/ckeditor5-link": "^10.1.0",
"@ckeditor/ckeditor5-list": "^11.0.3",
"@ckeditor/ckeditor5-paragraph": "^10.0.4",
"@ckeditor/ckeditor5-typing": "^11.0.2",
"@ckeditor/ckeditor5-undo": "^10.0.4",
"@ckeditor/ckeditor5-widget": "^10.3.1",
"eslint": "^5.5.0",

@@ -43,0 +43,0 @@ "eslint-config-ckeditor5": "^1.0.7",

@@ -152,3 +152,3 @@ /**

// First, convert elements.
const modelRange = ModelRange.createIn( modelElementOrFragment );
const modelRange = ModelRange._createIn( modelElementOrFragment );

@@ -205,3 +205,3 @@ const viewDocumentFragment = new ViewDocumentFragment();

this.model.enqueueChange( 'transparent', writer => {
writer.insert( this.parse( data, modelRoot ), modelRoot );
writer.insert( this.parse( data, modelRoot ), modelRoot, 0 );
} );

@@ -232,4 +232,4 @@

writer.remove( ModelRange.createIn( modelRoot ) );
writer.insert( this.parse( data, modelRoot ), modelRoot );
writer.remove( writer.createRangeIn( modelRoot ) );
writer.insert( this.parse( data, modelRoot ), modelRoot, 0 );
} );

@@ -303,3 +303,3 @@ }

const elementRange = ModelRange.createIn( element );
const elementRange = ModelRange._createIn( element );

@@ -306,0 +306,0 @@ for ( const marker of doc.model.markers ) {

@@ -422,2 +422,5 @@ /**

* For example, `<image src='foo.jpg'></image>` is converted to `<img src='foo.jpg'></img>` (the same attribute key and value).
* This type of converters is intended to be used with {@link module:engine/model/element~Element model element} nodes.
* To convert text attributes {@link module:engine/conversion/conversion~Conversion#attributeToElement `attributeToElement converter`}
* should be set up.
*

@@ -424,0 +427,0 @@ * // A simple conversion from the `source` model attribute to the `src` view attribute (and vice versa).

@@ -11,5 +11,5 @@ /**

import ViewAttributeElement from '../view/attributeelement';
import ViewRange from '../view/range';
import DocumentSelection from '../model/documentselection';
import log from '@ckeditor/ckeditor5-utils/src/log';
import { cloneDeep } from 'lodash-es';

@@ -51,3 +51,4 @@

* @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view A view element definition or a function
* that takes the model element and view writer as parameters and returns a view container element.
* that takes the model element and {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}
* as parameters and returns a view container element.
* @returns {Function} Conversion helper.

@@ -128,3 +129,4 @@ */

* @param {module:engine/view/elementdefinition~ElementDefinition|Function|Object} config.view A view element definition or a function
* that takes the model attribute value and view writer as parameters and returns a view attribute element. If `config.model.values` is
* that takes the model attribute value and {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}
* as parameters and returns a view attribute element. If `config.model.values` is
* given, `config.view` should be an object assigning values from `config.model.values` to view element definitions or functions.

@@ -539,3 +541,3 @@ * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.

const viewRange = new ViewRange( viewStart, viewEnd );
const viewRange = conversionApi.writer.createRange( viewStart, viewEnd );

@@ -547,3 +549,3 @@ // Trim the range to remove in case some UI elements are on the view range boundaries.

// 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 );

@@ -634,3 +636,3 @@ }

for ( const element of elements ) {
conversionApi.writer.clear( ViewRange.createOn( element ), element );
conversionApi.writer.clear( conversionApi.writer.createRangeOn( element ), element );
}

@@ -693,2 +695,45 @@

// If model item cannot be mapped to a view element, it means item is not an `Element` instance but a `TextProxy` node.
// Only elements can have attributes in a view so do not proceed for anything else (#1587).
if ( !viewElement ) {
/**
* This error occurs when a {@link module:engine/model/textproxy~TextProxy text node's} attribute is to be downcasted
* by {@link module:engine/conversion/conversion~Conversion#attributeToAttribute `Attribute to Attribute converter`}.
* In most cases it is caused by converters misconfiguration when only "generic" converter is defined:
*
* editor.conversion.for( 'downcast' ).add( downcastAttributeToAttribute( {
* model: 'attribute-name',
* view: 'attribute-name'
* } ) );
*
* and given attribute is used on text node, for example:
*
* model.change( writer => {
* writer.insertText( 'Foo', { 'attribute-name': 'bar' }, parent, 0 );
* } );
*
* In such cases, to convert the same attribute for both {@link module:engine/model/element~Element}
* and {@link module:engine/model/textproxy~TextProxy `Text`} nodes, text specific
* {@link module:engine/conversion/conversion~Conversion#attributeToElement `Attribute to Element converter`}
* with higher {@link module:utils/priorities~PriorityString priority} must also be defined:
*
* conversion.for( 'downcast' ).add( downcastAttributeToElement( {
* model: {
* key: 'attribute-name',
* name: '$text'
* },
* view: ( value, writer ) => {
* return writer.createAttributeElement( 'span', { 'attribute-name': value } );
* },
* converterPriority: 'high'
* } ) );
*
* @error conversion-attribute-to-attribute-on-text
*/
log.warn( 'conversion-attribute-to-attribute-on-text: ' +
'Trying to convert text node\'s attribute with attribute-to-attribute converter.' );
return;
}
// First remove the old attribute if there was one.

@@ -911,3 +956,3 @@ if ( data.attributeOldValue !== null && oldAttribute ) {

// 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 );

@@ -974,3 +1019,3 @@ }

if ( element.is( 'attributeElement' ) ) {
conversionApi.writer.unwrap( ViewRange.createOn( element ), viewHighlightElement );
conversionApi.writer.unwrap( conversionApi.writer.createRangeOn( element ), viewHighlightElement );
} else {

@@ -977,0 +1022,0 @@ // if element.is( 'containerElement' ).

@@ -134,3 +134,3 @@ /**

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' ) {

@@ -170,3 +170,3 @@ this.convertRemove( entry.position, entry.length, entry.name, writer );

const item = value.item;
const itemRange = Range.createFromPositionAndShift( value.previousPosition, value.length );
const itemRange = Range._createFromPositionAndShift( value.previousPosition, value.length );
const data = {

@@ -231,3 +231,3 @@ item,

const item = value.item;
const itemRange = Range.createFromPositionAndShift( value.previousPosition, value.length );
const itemRange = Range._createFromPositionAndShift( value.previousPosition, value.length );
const data = {

@@ -349,3 +349,3 @@ item,

const data = { item, range: Range.createOn( item ), markerName, markerRange };
const data = { item, range: Range._createOn( item ), markerName, markerRange };

@@ -502,5 +502,4 @@ this.fire( eventName, data, this.conversionApi );

* @param {Object} data Additional information about the change.
* @param {module:engine/model/position~Position} data.sourcePosition Position from where the range has been removed.
* @param {module:engine/model/range~Range} data.range Removed range (in {@link module:engine/model/document~Document#graveyard
* graveyard root}).
* @param {module:engine/model/position~Position} data.position Position from which the node has been removed.
* @param {Number} data.length Offset size of the removed node.
* @param {Object} conversionApi Conversion interface to be used by callback, passed in `DowncastDispatcher` constructor.

@@ -510,4 +509,8 @@ */

/**
* Fired when attribute has been added/changed/removed from a node. Also fired when collapsed model selection attribute is converted.
* Fired in the following cases:
*
* * when an attribute has been added, changed, or removed from a node,
* * when a node with an attribute is inserted,
* * when collapsed model selection attribute is converted.
*
* `attribute` is a namespace for a class of events. Names of actually called events follow this pattern:

@@ -514,0 +517,0 @@ * `attribute:attributeKey:name`. `attributeKey` is the key of added/changed/removed attribute.

@@ -104,3 +104,3 @@ /**

data.modelPosition = ModelPosition.createFromParentAndOffset( modelParent, modelOffset );
data.modelPosition = ModelPosition._createAt( modelParent, modelOffset );
}, { priority: 'low' } );

@@ -107,0 +107,0 @@ }

@@ -64,2 +64,3 @@ /**

* const insertPosition = conversionApi.mapper.toViewPosition( data.range.start );
* const viewWriter = conversionApi.writer;
*

@@ -66,0 +67,0 @@ * // Check if the `image` element has children.

@@ -9,3 +9,2 @@ /**

import ModelRange from '../model/range';
import ModelPosition from '../model/position';

@@ -362,3 +361,3 @@ import { cloneDeep } from 'lodash-es';

// Convert children and insert to element.
const childrenResult = conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( modelElement ) );
const childrenResult = conversionApi.convertChildren( data.viewItem, conversionApi.writer.createPositionAt( modelElement, 0 ) );

@@ -371,3 +370,3 @@ // Consume appropriate value from consumable values list.

// 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

@@ -377,3 +376,3 @@ // element, so we need to move range after parent of the last converted child.

// after: <allowed>[<converted><child></child></converted><child></child><converted>]</converted></allowed>
ModelPosition.createAfter( childrenResult.modelCursor.parent )
conversionApi.writer.createPositionAfter( childrenResult.modelCursor.parent )
);

@@ -387,3 +386,3 @@

if ( splitResult.cursorParent ) {
data.modelCursor = ModelPosition.createAt( splitResult.cursorParent );
data.modelCursor = conversionApi.writer.createPositionAt( splitResult.cursorParent, 0 );

@@ -610,3 +609,3 @@ // Otherwise just continue after inserted element.

data.modelRange = ModelRange.createFromPositionAndShift( data.modelCursor, text.offsetSize );
data.modelRange = ModelRange._createFromPositionAndShift( data.modelCursor, text.offsetSize );
data.modelCursor = data.modelRange.end;

@@ -613,0 +612,0 @@ }

@@ -74,6 +74,12 @@ /**

* // Convert children to paragraph.
* const { modelRange } = conversionApi.convertChildren( data.viewItem, Position.createAt( paragraph ) );
* 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
* );
*

@@ -376,3 +382,3 @@ * // Continue conversion inside paragraph.

// Create ModelTreeWalker.
const range = ModelRange.createIn( modelItem ).getItems();
const range = ModelRange._createIn( modelItem ).getItems();

@@ -390,10 +396,10 @@ // Walk through DocumentFragment and collect marker elements.

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();
}

@@ -425,3 +431,3 @@

position = ModelPosition.createAt( current );
position = ModelPosition._createAt( current, 0 );
}

@@ -428,0 +434,0 @@

@@ -314,3 +314,3 @@ /**

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() );

@@ -334,3 +334,3 @@ const nodeString = nodes.length > 1 ? `[ ${ nodes.length } ]` : nodes[ 0 ];

sandbox.mock( MoveOperation.prototype, 'toString', function() {
const range = ModelRange.createFromPositionAndShift( this.sourcePosition, this.howMany );
const range = ModelRange._createFromPositionAndShift( this.sourcePosition, this.howMany );

@@ -337,0 +337,0 @@ return getClassName( this ) + `( ${ this.baseVersion } ): ${ range } -> ${ this.targetPosition }`;

@@ -41,3 +41,3 @@ /**

/**
* Writes the content of the {@link module:engine/model/document~Document document} to an HTML-like string.
* Writes the content of a model {@link module:engine/model/document~Document document} to an HTML-like string.
*

@@ -76,5 +76,6 @@ * **Note:** A {@link module:engine/model/text~Text text} node that contains attributes will be represented as:

/**
* Sets the content of the {@link module:engine/model/document~Document document} provided as an HTML-like string.
* Sets the content of a model {@link module:engine/model/document~Document document} provided as an HTML-like string.
*
* **Note:** Remember to register elements in the {@link module:engine/model/model~Model#schema model's schema} before inserting them.
* **Note:** Remember to register elements in the {@link module:engine/model/model~Model#schema model's schema} before
* trying to use them.
*

@@ -120,3 +121,3 @@ * **Note:** To create a {@link module:engine/model/text~Text text} node that contains attributes use:

// Replace existing model in document by new one.
writer.remove( ModelRange.createIn( modelRoot ) );
writer.remove( writer.createRangeIn( modelRoot ) );
writer.insert( modelDocumentFragment, modelRoot );

@@ -175,3 +176,3 @@

if ( node instanceof RootElement || node instanceof ModelDocumentFragment ) {
range = ModelRange.createIn( node );
range = model.createRangeIn( node );
} else {

@@ -181,7 +182,7 @@ // Node is detached - create new document fragment.

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 )
);

@@ -399,5 +400,5 @@ }

conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( element ) );
conversionApi.convertChildren( data.viewItem, ModelPosition._createAt( element, 0 ) );
data.modelRange = ModelRange.createOn( element );
data.modelRange = ModelRange._createOn( element );
data.modelCursor = data.modelRange.end;

@@ -429,3 +430,3 @@

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

@@ -432,0 +433,0 @@

@@ -83,3 +83,3 @@ /**

/**
* Sets the content of the {@link module:engine/view/document~Document document} provided as an HTML-like string.
* Sets the content of a view {@link module:engine/view/document~Document document} provided as an HTML-like string.
*

@@ -115,5 +115,6 @@ * @param {module:engine/view/view~View} view

* Converts view elements to HTML-like string representation.
*
* A root element can be provided as {@link module:engine/view/text~Text text}:
*
* const text = new Text( 'foobar' );
* const text = downcastWriter.createText( 'foobar' );
* stringify( text ); // 'foobar'

@@ -123,3 +124,3 @@ *

*
* const element = new Element( 'p', null, new Text( 'foobar' ) );
* const element = downcastWriter.createElement( 'p', null, downcastWriter.createText( 'foobar' ) );
* stringify( element ); // '<p>foobar</p>'

@@ -129,6 +130,6 @@ *

*
* const text = new Text( 'foobar' );
* const b = new Element( 'b', { name: 'test' }, text );
* const p = new Element( 'p', { style: 'color:red;' } );
* const fragment = new DocumentFragment( [ p, b ] );
* const text = downcastWriter.createText( 'foobar' );
* const b = downcastWriter.createElement( 'b', { name: 'test' }, text );
* const p = downcastWriter.createElement( 'p', { style: 'color:red;' } );
* const fragment = downcastWriter.createDocumentFragment( [ p, b ] );
*

@@ -138,10 +139,10 @@ * stringify( fragment ); // '<p style="color:red;"></p><b name="test">foobar</b>'

* Additionally, a {@link module:engine/view/documentselection~DocumentSelection selection} instance can be provided.
* Ranges from the selection will then be included in output data.
* Ranges from the selection will then be included in the output data.
* If a range position is placed inside the element node, it will be represented with `[` and `]`:
*
* 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( p, 0, p, 1 )
* const text = downcastWriter.createText( 'foobar' );
* const b = downcastWriter.createElement( 'b', null, text );
* const p = downcastWriter.createElement( 'p', null, b );
* const selection = downcastWriter.createSelection(
* downcastWriter.createRangeIn( p )
* );

@@ -153,6 +154,8 @@ *

*
* 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 text = downcastWriter.createText( 'foobar' );
* const b = downcastWriter.createElement( 'b', null, text );
* const p = downcastWriter.createElement( 'p', null, b );
* const selection = downcastWriter.createSelection(
* downcastWriter.createRange( downcastWriter.createPositionAt( text, 1 ), downcastWriter.createPositionAt( text, 5 ) )
* );
*

@@ -168,6 +171,6 @@ * stringify( p, selection ); // '<p><b>f{ooba}r</b></p>'

*
* const text = new Text( 'foobar' );
* const selection = new Selection( [
* Range.createFromParentsAndOffsets( text, 0, text, 1 ) ),
* Range.createFromParentsAndOffsets( text, 3, text, 5 ) )
* const text = downcastWriter.createText( 'foobar' );
* const selection = downcastWriter.createSelection( [
* downcastWriter.createRange( downcastWriter.createPositionAt( text, 0 ), downcastWriter.createPositionAt( text, 1 ) ),
* downcastWriter.createRange( downcastWriter.createPositionAt( text, 3 ), downcastWriter.createPositionAt( text, 5 ) )
* ] );

@@ -182,5 +185,5 @@ *

*
* const text = new Text( 'foobar' );
* const range = Range.createFromParentsAndOffsets( text, 0, text, 1 );
* const position = new Position( text, 3 );
* const text = downcastWriter.createText( 'foobar' );
* const range = downcastWriter.createRange( downcastWriter.createPositionAt( text, 0 ), downcastWriter.createPositionAt( text, 1 ) );
* const position = downcastWriter.createPositionAt( text, 3 );
*

@@ -197,6 +200,6 @@ * stringify( text, range ); // '{f}oobar'

*
* const attribute = new AttributeElement( 'b' );
* const container = new ContainerElement( 'p' );
* const empty = new EmptyElement( 'img' );
* const ui = new UIElement( 'span' );
* const attribute = downcastWriter.createAttributeElement( 'b' );
* const container = downcastWriter.createContainerElement( 'p' );
* const empty = downcastWriter.createEmptyElement( 'img' );
* const ui = downcastWriter.createUIElement( 'span' );
* getData( attribute, null, { showType: true } ); // '<attribute:b></attribute:b>'

@@ -210,3 +213,3 @@ * getData( container, null, { showType: true } ); // '<container:p></container:p>'

*
* const attribute = new AttributeElement( 'b' );
* const attribute = downcastWriter.createAttributeElement( 'b' );
* attribute._priority = 20;

@@ -218,3 +221,3 @@ * getData( attribute, null, { showPriority: true } ); // <b view-priority="20"></b>

*
* const attribute = new AttributeElement( 'span' );
* const attribute = downcastWriter.createAttributeElement( 'span' );
* attribute._id = 'marker:foo';

@@ -263,3 +266,3 @@ * getData( attribute, null, { showAttributeElementId: true } ); // <span view-id="marker:foo"></span>

/**
* Parses an HTML-like string and returns view tree nodes.
* Parses an HTML-like string and returns a view tree.
* A simple string will be converted to a {@link module:engine/view/text~Text text} node:

@@ -1065,3 +1068,3 @@ *

// @param {String} priorityString
// returns {Number|Null}
// returns {Number|null}
function _convertPriority( priorityString ) {

@@ -1068,0 +1071,0 @@ const priority = parseInt( priorityString, 10 );

@@ -173,3 +173,3 @@ /**

const range = Range.createFromPositionAndShift( operation.position, 1 );
const range = Range._createFromPositionAndShift( operation.position, 1 );

@@ -395,6 +395,6 @@ for ( const marker of this._markerCollection.getMarkersIntersectingRange( 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 ) );
}

@@ -428,3 +428,3 @@

// Keep chronological order of operations.
return a.changeCount < b.changeCount ? -1 : 1;
return a.changeCount - b.changeCount;
}

@@ -832,3 +832,3 @@

type: 'insert',
position: Position.createFromParentAndOffset( parent, offset ),
position: Position._createAt( parent, offset ),
name,

@@ -852,3 +852,3 @@ length: 1,

type: 'remove',
position: Position.createFromParentAndOffset( parent, offset ),
position: Position._createAt( parent, offset ),
name,

@@ -887,3 +887,3 @@ length: 1,

position: range.start,
range: Range.createFromRange( range ),
range: range.clone(),
length: 1,

@@ -907,3 +907,3 @@ attributeKey: key,

position: range.start,
range: Range.createFromRange( range ),
range: range.clone(),
length: 1,

@@ -958,3 +958,3 @@ attributeKey: key,

_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 ) );

@@ -961,0 +961,0 @@ for ( const item of range.getItems( { shallow: true } ) ) {

@@ -11,4 +11,2 @@ /**

import Differ from './differ';
import Range from './range';
import Position from './position';
import RootElement from './rootelement';

@@ -338,10 +336,11 @@ import History from './history';

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 );
}

@@ -348,0 +347,0 @@

@@ -14,3 +14,2 @@ /**

import Selection from './selection';
import Position from './position';
import LiveRange from './liverange';

@@ -336,3 +335,4 @@ import Text from './text';

*
* 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.
*

@@ -755,3 +755,3 @@ * @see module:engine/model/writer~Writer#setSelectionFocus

const liveRange = LiveRange.createFromRange( range );
const liveRange = LiveRange.fromRange( range );

@@ -1020,3 +1020,3 @@ liveRange.on( 'change:range', ( evt, oldRange, data ) => {

// This is a good candidate for a fixed selection range.
const positionCandidate = Position.createFromPosition( removedRangeStart );
const positionCandidate = removedRangeStart.clone();

@@ -1023,0 +1023,0 @@ // Find a range that is a correct selection range and is closest to the start of removed range.

@@ -66,23 +66,27 @@ /**

/**
* @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}

@@ -93,5 +97,6 @@ */

* @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}

@@ -137,3 +142,3 @@ */

if ( !this.isEqual( result ) ) {
const oldPosition = Position.createFromPosition( this );
const oldPosition = this.toPosition();

@@ -140,0 +145,0 @@ this.path = result.path;

@@ -44,15 +44,26 @@ /**

/**
* @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}

@@ -62,9 +73,7 @@ */

/**
* @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}

@@ -74,6 +83,8 @@ */

/**
* @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}

@@ -135,3 +146,3 @@ */

const ranges = this.getTransformedByOperation( operation );
const result = Range.createFromRanges( ranges );
const result = Range._createFromRanges( ranges );

@@ -156,3 +167,3 @@ const boundariesChanged = !result.isEqual( this );

const oldRange = Range.createFromRange( this );
const oldRange = this.toRange();

@@ -165,3 +176,3 @@ this.start = result.start;

// 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 } );
}

@@ -168,0 +179,0 @@ }

@@ -11,4 +11,2 @@ /**

import LiveRange from './liverange';
import Position from './position';
import Range from './range';
import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';

@@ -105,3 +103,3 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';

if ( !oldRange.isEqual( range ) ) {
oldMarker._attachLiveRange( LiveRange.createFromRange( range ) );
oldMarker._attachLiveRange( LiveRange.fromRange( range ) );
hasChanged = true;

@@ -127,3 +125,3 @@ }

const liveRange = LiveRange.createFromRange( range );
const liveRange = LiveRange.fromRange( range );
const marker = new Marker( markerName, liveRange, managedUsingOperations, affectsData );

@@ -402,3 +400,3 @@

return Position.createFromPosition( this._liveRange.start );
return this._liveRange.start.clone();
}

@@ -416,3 +414,3 @@

return Position.createFromPosition( this._liveRange.end );
return this._liveRange.end.clone();
}

@@ -437,3 +435,3 @@

return Range.createFromRange( this._liveRange );
return this._liveRange.toRange();
}

@@ -440,0 +438,0 @@

@@ -19,2 +19,4 @@ /**

import ModelRange from './range';
import ModelPosition from './position';
import ModelSelection from './selection';

@@ -226,3 +228,3 @@ import insertContent from './utils/insertcontent';

/**
* Inserts content into the editor (specified selection) as one would expect the paste
* Inserts content at the position in the editor specified by the selection, as one would expect the paste
* functionality to work.

@@ -233,3 +235,3 @@ *

* to its target position at the end of the process.
* It can split elements, merge them, wrap bare text nodes in paragraphs, etc. – just like the
* It can split elements, merge them, wrap bare text nodes with paragraphs, etc. &mdash; just like the
* pasting feature should do.

@@ -250,4 +252,4 @@ *

*
* So, while this method may seem similar to CKEditor 4's `editor.insertHtml()` (in fact, both methods
* are used for paste-like content insertion), CKEditor 5's method cannot be use to insert arbitrary HTML
* So, while this method may seem similar to CKEditor 4 `editor.insertHtml()` (in fact, both methods
* are used for paste-like content insertion), the CKEditor 5 method cannot be use to insert arbitrary HTML
* unless converters are defined for all elements and attributes in that HTML.

@@ -259,3 +261,3 @@ *

*
* // Let's create a document fragment containing such a content:
* // Let's create a document fragment containing such content as:
* //

@@ -281,22 +283,22 @@ * // <paragrap>foo</paragraph>

*
* // insertContent() doesn't have to be used in a change() block. It can, though,
* // insertContent() does not have to be used in a change() block. It can, though,
* // so this code could be moved to the callback defined above.
* editor.model.insertContent( docFrag );
*
* Using `insertContent()` with HTML string converted to a model document fragment (similar to the pasting mechanism):
* Using `insertContent()` with an HTML string converted to a model document fragment (similar to the pasting mechanism):
*
* // You can create your own HtmlDataProcessor instance or use editor.data.processor
* // if you haven't overridden the default one (which is HtmlDataProcessor instance).
* // if you have not overridden the default one (which is the HtmlDataProcessor instance).
* const htmlDP = new HtmlDataProcessor();
*
* // Convert an HTML string to a view document fragment.
* // Convert an HTML string to a view document fragment:
* const viewFragment = htmlDP.toView( htmlString );
*
* // Convert a view document fragment to a model document fragment
* // in the context of $root. This conversion takes schema into
* // the account so if e.g. the view document fragment contained a bare text node
* // then that text node cannot be a child of $root, so it will be automatically
* // wrapped with a <paragraph>. You can define the context yourself (in the 2nd parameter),
* // Convert the view document fragment to a model document fragment
* // in the context of $root. This conversion takes the schema into
* // account so if, for example, the view document fragment contained a bare text node,
* // this text node cannot be a child of $root, so it will be automatically
* // wrapped with a <paragraph>. You can define the context yourself (in the second parameter),
* // and e.g. convert the content like it would happen in a <paragraph>.
* // Note: the clipboard feature uses a custom context called $clipboardHolder
* // Note: The clipboard feature uses a custom context called $clipboardHolder
* // which has a loosened schema.

@@ -314,5 +316,8 @@ * const modelFragment = editor.data.toModel( viewFragment );

*
* // Insert text at given position - document selection will not be modified.
* // Insert text at a given position - the document selection will not be modified.
* editor.model.change( writer => {
* editor.model.insertContent( writer.createText( 'x' ), Position.createAt( doc.getRoot(), 2 ) );
* editor.model.insertContent( writer.createText( 'x' ), doc.getRoot(), 2 );
*
* // Which is a shorthand for:
* editor.model.insertContent( writer.createText( 'x' ), writer.createPositionAt( doc.getRoot(), 2 ) );
* } );

@@ -323,10 +328,10 @@ *

*
* // Insert text replacing 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.change( writer => {
* editor.model.insertContent( writer.createText( 'x' ), selection );
*
* // insertContent() modifies the passed selection instance so it can be used to set the document selection.
* // Note: This is not necessary when you passed document selection to insertContent().
* // Note: This is not necessary when you passed the document selection to insertContent().
* writer.setSelection( selection );

@@ -338,8 +343,10 @@ * } );

* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|
* module:engine/model/position~Position|module:engine/model/element~Element|
* module:engine/model/position~Position|module:engine/model/item~Item|
* Iterable.<module:engine/model/range~Range>|module:engine/model/range~Range|null} [selectable=model.document.selection]
* Selection into which the content should be inserted. If not provided the current model document selection will be used.
* The selection into which the content should be inserted. If not provided the current model document selection will be used.
* @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] To be used when a model item was passed as `selectable`.
* This param defines a position in relation to that item.
*/
insertContent( content, selectable ) {
insertContent( this, content, selectable );
insertContent( content, selectable, placeOrOffset ) {
insertContent( this, content, selectable, placeOrOffset );
}

@@ -361,3 +368,2 @@

* Selection of which the content should be deleted.
* @param {module:engine/model/batch~Batch} batch Batch to which the operations will be added.
* @param {Object} [options]

@@ -453,6 +459,7 @@ * @param {Boolean} [options.leaveUnmerged=false] Whether to merge elements after removing the content of the selection.

/**
* 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}.
*

@@ -464,3 +471,3 @@ * @param {module:engine/model/range~Range|module:engine/model/element~Element} rangeOrElement Range or element to check.

if ( rangeOrElement instanceof ModelElement ) {
rangeOrElement = ModelRange.createIn( rangeOrElement );
rangeOrElement = ModelRange._createIn( rangeOrElement );
}

@@ -483,2 +490,204 @@

/**
* 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.<Number>} 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>|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}.

@@ -485,0 +694,0 @@ */

@@ -102,3 +102,3 @@ /**

* @readonly
* @type {Number|Null}
* @type {Number|null}
*/

@@ -105,0 +105,0 @@ get startOffset() {

@@ -52,3 +52,3 @@ /**

*/
this.range = Range.createFromRange( range );
this.range = range.clone();

@@ -55,0 +55,0 @@ /**

@@ -11,3 +11,2 @@ /**

import Operation from './operation';
import Position from '../position';
import Range from '../range';

@@ -40,3 +39,3 @@ import { _remove } from './utils';

*/
this.sourcePosition = Position.createFromPosition( sourcePosition );
this.sourcePosition = sourcePosition.clone();

@@ -87,3 +86,3 @@ /**

_execute() {
_remove( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ) );
_remove( Range._createFromPositionAndShift( this.sourcePosition, this.howMany ) );
}

@@ -90,0 +89,0 @@

@@ -42,3 +42,3 @@ /**

*/
this.position = Position.createFromPosition( position );
this.position = position.clone();
this.position.stickiness = 'toNone';

@@ -45,0 +45,0 @@

@@ -44,3 +44,3 @@ /**

*/
this.oldRange = oldRange ? Range.createFromRange( oldRange ) : null;
this.oldRange = oldRange ? oldRange.clone() : null;

@@ -53,3 +53,3 @@ /**

*/
this.newRange = newRange ? Range.createFromRange( newRange ) : null;
this.newRange = newRange ? newRange.clone() : null;

@@ -56,0 +56,0 @@ /**

@@ -48,3 +48,3 @@ /**

*/
this.sourcePosition = Position.createFromPosition( sourcePosition );
this.sourcePosition = sourcePosition.clone();
// This is, and should always remain, the first position in its parent.

@@ -65,3 +65,3 @@ this.sourcePosition.stickiness = 'toPrevious';

*/
this.targetPosition = Position.createFromPosition( targetPosition );
this.targetPosition = targetPosition.clone();
// Except of a rare scenario in `MergeOperation` x `MergeOperation` transformation,

@@ -76,3 +76,3 @@ // this is, and should always remain, the last position in its parent.

*/
this.graveyardPosition = Position.createFromPosition( graveyardPosition );
this.graveyardPosition = graveyardPosition.clone();
}

@@ -176,6 +176,6 @@

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 );
}

@@ -182,0 +182,0 @@

@@ -43,3 +43,3 @@ /**

*/
this.sourcePosition = Position.createFromPosition( sourcePosition );
this.sourcePosition = sourcePosition.clone();
// `'toNext'` because `sourcePosition` is a bit like a start of the moved range.

@@ -60,3 +60,3 @@ this.sourcePosition.stickiness = 'toNext';

*/
this.targetPosition = Position.createFromPosition( targetPosition );
this.targetPosition = targetPosition.clone();
this.targetPosition.stickiness = 'toNone';

@@ -177,3 +177,3 @@ }

_execute() {
_move( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ), this.targetPosition );
_move( Range._createFromPositionAndShift( this.sourcePosition, this.howMany ), this.targetPosition );
}

@@ -180,0 +180,0 @@

@@ -72,3 +72,3 @@ /**

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 );
}

@@ -82,3 +82,3 @@

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 );
}

@@ -85,0 +85,0 @@

@@ -44,3 +44,3 @@ /**

*/
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

@@ -73,3 +73,3 @@ // will be left in the original element.

*/
this.graveyardPosition = graveyardPosition ? Position.createFromPosition( graveyardPosition ) : null;
this.graveyardPosition = graveyardPosition ? graveyardPosition.clone() : null;

@@ -186,3 +186,3 @@ if ( this.graveyardPosition ) {

if ( this.graveyardPosition ) {
_move( Range.createFromPositionAndShift( this.graveyardPosition, 1 ), this.insertionPosition );
_move( Range._createFromPositionAndShift( this.graveyardPosition, 1 ), this.insertionPosition );
} else {

@@ -194,4 +194,5 @@ const newElement = splitElement._clone();

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 )
);

@@ -198,0 +199,0 @@

@@ -19,16 +19,21 @@ /**

*
* **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,

@@ -364,3 +369,3 @@ * {@link module:engine/model/position~Position#parent} and some other properties and methods will throw errors.

getShiftedBy( shift ) {
const shifted = Position.createFromPosition( this );
const shifted = this.clone();

@@ -453,9 +458,9 @@ const offset = shifted.offset + shift;

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;

@@ -544,3 +549,3 @@

default:
result = Position.createFromPosition( this );
result = Position._createAt( this );
break;

@@ -619,3 +624,3 @@ }

} else if ( this.isEqual( operation.deletionPosition ) ) {
pos = Position.createFromPosition( operation.deletionPosition );
pos = Position._createAt( operation.deletionPosition );
} else {

@@ -638,3 +643,3 @@ pos = this._getTransformedByMove( operation.deletionPosition, operation.graveyardPosition, 1 );

_getTransformedByDeletion( deletePosition, howMany ) {
const transformed = Position.createFromPosition( this );
const transformed = Position._createAt( this );

@@ -687,3 +692,3 @@ // This position can't be affected if deletion was in a different root.

_getTransformedByInsertion( insertPosition, howMany ) {
const transformed = Position.createFromPosition( this );
const transformed = Position._createAt( this );

@@ -731,3 +736,3 @@ // This position can't be affected if insertion was in a different root.

// 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 );
}

@@ -762,5 +767,5 @@

*
* 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`

@@ -786,3 +791,3 @@ *

// 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;

@@ -814,2 +819,11 @@

/**
* 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:

@@ -822,16 +836,15 @@ *

*
* 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=0] Offset or one of the flags. Used only when
* @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 {

@@ -843,10 +856,31 @@ const node = itemOrPosition;

} else if ( offset == 'before' ) {
return this.createBefore( node );
return this._createBefore( node );
} else if ( offset == 'after' ) {
return this.createAfter( node );
} else if ( !offset ) {
offset = 0;
return this._createAfter( node );
} else if ( offset !== 0 && !offset ) {
/**
* {@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-createPositionAt-offset-required
*/
throw new CKEditorError(
'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 );
}

@@ -860,4 +894,5 @@ }

* @returns {module:engine/model/position~Position}
* @protected
*/
static createAfter( item ) {
static _createAfter( item ) {
if ( !item.parent ) {

@@ -873,3 +908,3 @@ /**

return this.createFromParentAndOffset( item.parent, item.endOffset );
return this._createAt( item.parent, item.endOffset );
}

@@ -882,4 +917,5 @@

* @returns {module:engine/model/position~Position}
* @protected
*/
static createBefore( item ) {
static _createBefore( item ) {
if ( !item.parent ) {

@@ -895,43 +931,6 @@ /**

return this.createFromParentAndOffset( item.parent, item.startOffset );
return this._createAt( 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;
}
/**
* Creates a `Position` instance from given plain object (i.e. parsed JSON string).

@@ -938,0 +937,0 @@ *

@@ -16,3 +16,9 @@ /**

/**
* 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}.
*/

@@ -23,4 +29,2 @@ export default class Range {

*
* **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.

@@ -36,3 +40,3 @@ * @param {module:engine/model/position~Position} [end] End position. If not set, range will be collapsed at `start` position.

*/
this.start = Position.createFromPosition( start );
this.start = Position._createAt( start );

@@ -45,3 +49,3 @@ /**

*/
this.end = end ? Position.createFromPosition( end ) : Position.createFromPosition( start );
this.end = end ? Position._createAt( end ) : Position._createAt( start );

@@ -141,3 +145,3 @@ // If the range is collapsed, treat in a similar way as a position and set its boundaries stickiness to 'toNone'.

containsItem( item ) {
const pos = Position.createBefore( item );
const pos = Position._createBefore( item );

@@ -173,12 +177,15 @@ return this.containsPosition( pos ) || this.start.isEqual( pos );

*
* 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 );

@@ -209,3 +216,3 @@ * // transformed array has two ranges: from [ 2, 7 ] to [ 3 ] and from [ 4 ] to [ 4, 0, 1 ]

// Ranges do not intersect, return the original range.
ranges.push( Range.createFromRange( this ) );
ranges.push( new Range( this.start, this.end ) );
}

@@ -222,7 +229,10 @@

*
* 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 ]

@@ -302,3 +312,3 @@ *

const pos = Position.createFromPosition( this.start );
const pos = Position._createAt( this.start );
let posParent = pos.parent;

@@ -425,3 +435,3 @@

return [ Range.createFromRange( this ) ];
return [ new Range( this.start, this.end ) ];
}

@@ -437,3 +447,3 @@

getTransformedByOperations( operations ) {
const ranges = [ Range.createFromRange( this ) ];
const ranges = [ new Range( this.start, this.end ) ];

@@ -491,2 +501,11 @@ for ( const operation of operations ) {

/**
* 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.

@@ -532,11 +551,15 @@ *

const start = this.start._getTransformedBySplitOperation( operation );
let end = this.end._getTransformedBySplitOperation( operation );
let end;
if ( this.end.isEqual( operation.insertionPosition ) ) {
end = this.end.getShiftedBy( 1 );
} else {
end = this.end._getTransformedBySplitOperation( operation );
}
// Below may happen when range contains graveyard element used by split operation.
if ( start.root != end.root ) {
// End position was next to the moved graveyard element and was moved with it.
// Fix it by using old `end` which has proper `root`.
end = this.end.getShiftedBy( -1 );
}
return new Range( start, end );

@@ -594,3 +617,3 @@ }

// Case 1.
start = Position.createFromPosition( end );
start = Position._createAt( end );
start.offset = 0;

@@ -620,13 +643,16 @@ } else {

*
* 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 ]

@@ -655,3 +681,3 @@ *

} else {
const range = Range.createFromRange( this );
const range = new Range( this.start, this.end );

@@ -696,3 +722,3 @@ range.start = range.start._getTransformedByInsertion( insertPosition, howMany );

// 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 );

@@ -788,2 +814,3 @@

*
* @protected
* @param {module:engine/model/position~Position} position Beginning of the range.

@@ -793,3 +820,3 @@ * @param {Number} shift How long the range should be.

*/
static createFromPositionAndShift( position, shift ) {
static _createFromPositionAndShift( position, shift ) {
const start = position;

@@ -802,36 +829,11 @@ const end = position.getShiftedBy( shift );

/**
* 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 ) );
}

@@ -842,25 +844,11 @@

*
* @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 );
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=0] 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 );
}
/**
* Combines all ranges from the passed array into a one range. At least one range has to be passed.

@@ -880,7 +868,7 @@ * Passed ranges must not have common parts.

*/
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()`}.
*

@@ -891,3 +879,3 @@ * @error range-create-from-ranges-empty-array

} else if ( ranges.length == 1 ) {
return this.createFromRange( ranges[ 0 ] );
return ranges[ 0 ].clone();
}

@@ -918,3 +906,3 @@

if ( ranges[ i ].end.isEqual( result.start ) ) {
result.start = Position.createFromPosition( ranges[ i ].start );
result.start = Position._createAt( ranges[ i ].start );
} else {

@@ -931,3 +919,3 @@ // If ranges are not starting/ending at the same position there is no point in looking further.

if ( ranges[ i ].start.isEqual( result.end ) ) {
result.end = Position.createFromPosition( ranges[ i ].end );
result.end = Position._createAt( ranges[ i ].end );
} else {

@@ -934,0 +922,0 @@ // If ranges are not starting/ending at the same position there is no point in looking further.

@@ -550,3 +550,3 @@ /**

if ( item.is( 'element' ) ) {
yield* this._getValidRangesForRange( Range.createIn( item ), attribute );
yield* this._getValidRangesForRange( Range._createIn( item ), attribute );
}

@@ -559,6 +559,6 @@

start = Position.createAfter( item );
start = Position._createAfter( item );
}
end = Position.createAfter( item );
end = Position._createAfter( item );
}

@@ -612,3 +612,3 @@

if ( value.type == type && this.isObject( value.item ) ) {
return Range.createOn( value.item );
return Range._createOn( value.item );
}

@@ -674,2 +674,12 @@

/**
* 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

@@ -1169,3 +1179,3 @@ */

* // Also check in [ rootElement, blockQuoteElement, paragraphElement ].
* schema.checkChild( Position.createAt( paragraphElement ), 'foo' );
* schema.checkChild( model.createPositionAt( paragraphElement, 0 ), 'foo' );
*

@@ -1172,0 +1182,0 @@ * // Check in [ rootElement, paragraphElement ].

@@ -39,37 +39,37 @@ /**

* // 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' );
*

@@ -79,3 +79,3 @@ * 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 } );
*

@@ -247,3 +247,3 @@ * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|

for ( const range of this._ranges ) {
yield Range.createFromRange( range );
yield new Range( range.start, range.end );
}

@@ -271,3 +271,3 @@ }

return first ? Range.createFromRange( first ) : null;
return first ? new Range( first.start, first.end ) : null;
}

@@ -294,3 +294,3 @@

return last ? Range.createFromRange( last ) : null;
return last ? new Range( last.start, last.end ) : null;
}

@@ -310,3 +310,3 @@

return first ? Position.createFromPosition( first.start ) : null;
return first ? first.start.clone() : null;
}

@@ -326,3 +326,3 @@

return lastRange ? Position.createFromPosition( lastRange.end ) : null;
return lastRange ? lastRange.end.clone() : null;
}

@@ -340,7 +340,7 @@

* // 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 );

@@ -350,3 +350,3 @@ *

* // Note: It doesn't copies selection attributes.
* const otherSelection = new Selection();
* const otherSelection = writer.createSelection();
* selection.setTo( otherSelection );

@@ -360,3 +360,3 @@ *

* // Sets collapsed selection at the given position.
* const position = new Position( root, path );
* const position = writer.createPositionFromPath( root, path );
* selection.setTo( position );

@@ -379,3 +379,3 @@ *

* // Sets backward selection.
* const selection = new Selection( range, { backward: true } );
* const selection = writer.createSelection( range, { backward: true } );
*

@@ -407,7 +407,7 @@ * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|

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 {

@@ -496,7 +496,8 @@ /**

*
* 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
* @param {Number|'end'|'before'|'after'} [offset=0] Offset or one of the flags. Used only when
* @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}.

@@ -516,3 +517,3 @@ */

const newFocus = Position.createAt( itemOrPosition, offset );
const newFocus = Position._createAt( itemOrPosition, offset );

@@ -682,3 +683,3 @@ if ( newFocus.compareWith( this.focus ) == 'same' ) {

// #984. Don't return the end block if the range ends right at its beginning.
if ( endBlock && !range.end.isTouching( Position.createAt( endBlock ) ) ) {
if ( endBlock && !range.end.isTouching( Position._createAt( endBlock, 0 ) ) ) {
yield endBlock;

@@ -701,4 +702,4 @@ }

containsEntireContent( element = this.anchor.root ) {
const limitStartPosition = Position.createAt( element );
const limitEndPosition = Position.createAt( element, 'end' );
const limitStartPosition = Position._createAt( element, 0 );
const limitEndPosition = Position._createAt( element, 'end' );

@@ -718,3 +719,3 @@ return limitStartPosition.isTouching( this.getFirstPosition() ) &&

this._checkRange( range );
this._ranges.push( Range.createFromRange( range ) );
this._ranges.push( new Range( range.start, range.end ) );
}

@@ -721,0 +722,0 @@

@@ -58,3 +58,4 @@ /**

*
* @returns {String}
* @readonly
* @type {String}
*/

@@ -61,0 +62,0 @@ get data() {

@@ -88,5 +88,5 @@ /**

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' ] );
}

@@ -212,3 +212,3 @@

const previousPosition = this.position;
const position = Position.createFromPosition( this.position );
const position = this.position.clone();
const parent = this._visitedParent;

@@ -287,3 +287,3 @@

const previousPosition = this.position;
const position = Position.createFromPosition( this.position );
const position = this.position.clone();
const parent = this._visitedParent;

@@ -385,6 +385,3 @@

* * 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

@@ -398,3 +395,3 @@ * the position after 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`.
*/

@@ -401,0 +398,0 @@

@@ -11,3 +11,2 @@ /**

import LivePosition from '../liveposition';
import Position from '../position';
import Range from '../range';

@@ -66,4 +65,3 @@ import DocumentSelection from '../documentselection';

const startPos = selRange.start;
const endPos = LivePosition.createFromPosition( selRange.end );
endPos.stickiness = 'toNext';
const endPos = LivePosition.fromPosition( selRange.end, 'toNext' );

@@ -123,6 +121,4 @@ // 2. Remove the content if there is any.

// If one of the positions is a root, then there's nothing more to merge (at least in the current state of implementation).
// Theoretically in this case we could unwrap the <p>: <$root>x[]<p>{}y</p></$root>, but we don't need to support it yet
// so let's just abort.
if ( !startParent.parent || !endParent.parent ) {
// If one of the positions is a limit element, then there's nothing to merge because we don't want to cross the limit boundaries.
if ( writer.model.schema.isLimit( startParent ) || writer.model.schema.isLimit( endParent ) ) {
return;

@@ -142,4 +138,4 @@ }

// <a><b>xy</b>[]</a><c>{}</c>
startPos = Position.createAfter( startParent );
endPos = Position.createBefore( endParent );
startPos = writer.createPositionAfter( startParent );
endPos = writer.createPositionBefore( endParent );

@@ -167,3 +163,3 @@ if ( !endPos.isEqual( startPos ) ) {

endPos = Position.createBefore( parentToRemove );
endPos = writer.createPositionBefore( parentToRemove );

@@ -217,4 +213,4 @@ writer.remove( parentToRemove );

writer.remove( Range.createIn( limitElement ) );
insertParagraph( writer, Position.createAt( limitElement ), selection );
writer.remove( writer.createRangeIn( limitElement ) );
insertParagraph( writer, writer.createPositionAt( limitElement, 0 ), selection );
}

@@ -221,0 +217,0 @@

@@ -10,5 +10,2 @@ /**

import Range from '../range';
import Position from '../position';
/**

@@ -67,5 +64,5 @@ * Gets a clone of the selected content.

} 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 )
);

@@ -102,6 +99,6 @@ }

// 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 ), 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' ) );

@@ -124,3 +121,3 @@ removeRangeContent( rightExcessRange, writer );

// 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.

@@ -150,3 +147,3 @@ //

while ( parent.parent && parent.isEmpty ) {
const removeRange = Range.createOn( parent );
const removeRange = writer.createRangeOn( parent );

@@ -153,0 +150,0 @@ parent = parent.parent;

@@ -36,4 +36,5 @@ /**

* Selection into which the content should be inserted.
* @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.
*/
export default function insertContent( model, content, selectable ) {
export default function insertContent( model, content, selectable, placeOrOffset ) {
model.change( writer => {

@@ -47,3 +48,3 @@ let selection;

} else {
selection = new Selection( selectable );
selection = writer.createSelection( selectable, placeOrOffset );
}

@@ -178,3 +179,3 @@

if ( this.nodeToSelect ) {
return Range.createOn( this.nodeToSelect );
return Range._createOn( this.nodeToSelect );
}

@@ -281,8 +282,7 @@

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();

@@ -312,15 +312,15 @@

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();
}

@@ -339,12 +339,12 @@

// <p>x</p>[]<p>y</p> => <p>x[]</p><p>y</p>
this.position = Position.createAt( mergePosRight.nodeBefore, 'end' );
this.position = Position._createAt( mergePosRight.nodeBefore, 'end' );
// OK: <p>xx[]</p> + <p>yy</p> => <p>xx[]yy</p> (when sticks to previous)
// NOK: <p>xx[]</p> + <p>yy</p> => <p>xxyy[]</p> (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();
}

@@ -436,3 +436,3 @@

const parent = this.position.parent;
this.position = Position.createBefore( parent );
this.position = this.writer.createPositionBefore( parent );

@@ -445,5 +445,5 @@ // Special case – parent is empty (<p>^</p>) so isAtStart == isAtEnd == true.

} 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 );

@@ -450,0 +450,0 @@ this.writer.split( this.position );

@@ -109,3 +109,3 @@ /**

if ( data.schema.isObject( value.item ) ) {
return Position.createAt( value.item, data.isForward ? 'after' : 'before' );
return Position._createAt( value.item, data.isForward ? 'after' : 'before' );
}

@@ -199,3 +199,3 @@

const root = start.root;
const searchEnd = Position.createAt( root, isForward ? 'end' : 0 );
const searchEnd = Position._createAt( root, isForward ? 'end' : 0 );

@@ -202,0 +202,0 @@ if ( isForward ) {

@@ -152,3 +152,3 @@ /**

if ( fixedPosition.nodeAfter && schema.isLimit( fixedPosition.nodeAfter ) ) {
return new Range( fixedPosition, Position.createAfter( fixedPosition.nodeAfter ) );
return new Range( fixedPosition, Position._createAfter( fixedPosition.nodeAfter ) );
}

@@ -203,5 +203,8 @@

// as limit elements might be nested directly inside (ie table > tableRow > tableCell).
const fixedStart = isStartInLimit ? expandSelectionOnIsLimitNode( Position.createAt( startLimitElement ), schema, 'start' ) : start;
const fixedEnd = isEndInLimit ? expandSelectionOnIsLimitNode( Position.createAt( endLimitElement ), schema, 'end' ) : end;
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;
return new Range( fixedStart, fixedEnd );

@@ -231,3 +234,3 @@ }

// 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 );
}

@@ -234,0 +237,0 @@

@@ -140,3 +140,3 @@ /**

*
* 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()`}.
*

@@ -157,9 +157,9 @@ * Note that if the item already has parent it will be removed from the previous parent.

* @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
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when
* second parameter is a {@link module:engine/model/item~Item model item}.
*/
insert( item, itemOrPosition, offset ) {
insert( item, itemOrPosition, offset = 0 ) {
this._assertWriterUsedCorrectly();
const position = Position.createAt( itemOrPosition, offset );
const position = Position._createAt( itemOrPosition, offset );

@@ -171,3 +171,3 @@ // If item has a parent already.

// If it's we just need to move it.
this.move( Range.createOn( item ), position );
this.move( Range._createOn( item ), position );

@@ -204,3 +204,3 @@ return;

// We need to migrate marker range from DocumentFragment to Document.
const rangeRootPosition = Position.createAt( markerRange.root );
const rangeRootPosition = Position._createAt( markerRange.root, 0 );
const range = new Range(

@@ -211,3 +211,3 @@ markerRange.start._getCombined( rangeRootPosition, position ),

this.addMarker( markerName, { range, usingOperation: true } );
this.addMarker( markerName, { range, usingOperation: true, affectsData: true } );
}

@@ -233,3 +233,3 @@ }

*
* 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()`}.
*

@@ -239,3 +239,3 @@ * @param {String} data Text data.

* @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
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when
* third parameter is a {@link module:engine/model/item~Item model item}.

@@ -267,3 +267,3 @@ */

*
* 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()`}.
*

@@ -273,3 +273,3 @@ * @param {String} name Name of the element.

* @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
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when
* third parameter is a {@link module:engine/model/item~Item model item}.

@@ -443,3 +443,3 @@ */

*
* 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()`}.
*

@@ -453,3 +453,3 @@ * Note that items can be moved only within the same tree. It means that you can move items within the same root

* @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
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when
* second parameter is a {@link module:engine/model/item~Item model item}.

@@ -478,3 +478,3 @@ */

const position = Position.createAt( itemOrPosition, offset );
const position = Position._createAt( itemOrPosition, offset );

@@ -516,3 +516,3 @@ if ( !isSameTree( range.root, position.root ) ) {

applyRemoveOperation( Position.createBefore( itemOrRange ), howMany, this.batch, this.model );
applyRemoveOperation( Position._createBefore( itemOrRange ), howMany, this.batch, this.model );
}

@@ -561,2 +561,93 @@ }

/**
* 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.<Number>} 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>|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.

@@ -571,3 +662,3 @@ *

this.move( Range.createIn( nodeAfter ), Position.createAt( nodeBefore, 'end' ) );
this.move( Range._createIn( nodeAfter ), Position._createAt( nodeBefore, 'end' ) );
this.remove( nodeAfter );

@@ -583,4 +674,4 @@ }

_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 );

@@ -619,3 +710,3 @@ const graveyard = position.root.document.graveyard;

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 );

@@ -682,3 +773,3 @@ this.batch.addOperation( renameOperation );

position = Position.createAfter( position.parent );
position = this.createPositionAfter( position.parent );
splitElement = position.parent;

@@ -689,3 +780,3 @@ } while ( splitElement !== limitElement );

position,
range: new Range( Position.createAt( firstSplitElement, 'end' ), Position.createAt( firstCopyElement ) )
range: new Range( Position._createAt( firstSplitElement, 'end' ), Position._createAt( firstCopyElement, 0 ) )
};

@@ -745,3 +836,3 @@ }

range.end.offset - range.start.offset,
Position.createAt( element, 0 ),
Position._createAt( element, 0 ),
version === null ? null : version + 1

@@ -772,3 +863,3 @@ );

this.move( Range.createIn( element ), Position.createAfter( element ) );
this.move( Range._createIn( element ), this.createPositionAfter( element ) );
this.remove( element );

@@ -1000,25 +1091,29 @@ }

/**
* 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 );

@@ -1065,3 +1160,3 @@ *

* 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.
*

@@ -1312,3 +1407,3 @@ * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition

} else {
range = new Range( Position.createBefore( item ), Position.createAfter( item ) );
range = new Range( Position._createBefore( item ), writer.createPositionAfter( item ) );

@@ -1315,0 +1410,0 @@ const version = range.root.document ? doc.version : null;

@@ -17,9 +17,12 @@ /**

/**
* Attributes are elements which define document presentation. They are mostly elements like `<b>` or `<span>`.
* Attributes can be broken and merged by the {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}.
* Attribute elements are used to represent formatting elements in the view (think – `<b>`, `<span style="font-size: 2em">`, etc.).
* Most often they are created when downcasting model text attributes.
*
* Editing engine does not define fixed HTML DTD. This is why the type of the {@link module:engine/view/element~Element} need to
* be defined by the feature developer. Creating an element you should use {@link module:engine/view/containerelement~ContainerElement}
* class or `AttributeElement`.
* Editing engine does not define a fixed HTML DTD. This is why a feature developer needs to choose between various
* types (container element, {@link module:engine/view/attributeelement~AttributeElement attribute element},
* {@link module:engine/view/emptyelement~EmptyElement empty element}, etc) when developing a feature.
*
* To create a new attribute element instance use the
* {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement `DowncastWriter#createAttributeElement()`} method.
*
* @extends module:engine/view/element~Element

@@ -29,7 +32,7 @@ */

/**
* Creates a attribute element.
* Creates an attribute element.
*
* @see module:engine/view/downcastwriter~DowncastWriter#createAttributeElement
* @see module:engine/view/element~Element
* @protected
* @see module:engine/view/element~Element
*/

@@ -71,3 +74,3 @@ constructor( name, attrs, children ) {

* @protected
* @member {Set|null}
* @member {Set.<module:engine/view/attributeelement~AttributeElement>|null}
*/

@@ -81,3 +84,3 @@ this._clonesGroup = null;

* @readonly
* @returns {Number}
* @type {Number}
*/

@@ -93,3 +96,3 @@ get priority() {

* @readonly
* @returns {String|Number}
* @type {String|Number}
*/

@@ -96,0 +99,0 @@ get id() {

@@ -14,32 +14,19 @@ /**

* Containers are elements which define document structure. They define boundaries for
* {@link module:engine/view/attributeelement~AttributeElement attributes}. They are mostly use for block elements like `<p>` or `<div>`.
* {@link module:engine/view/attributeelement~AttributeElement attributes}. They are mostly used for block elements like `<p>` or `<div>`.
*
* Editing engine does not define fixed HTML DTD. This is why the type of the {@link module:engine/view/element~Element} need to
* be defined by the feature developer.
* Editing engine does not define a fixed HTML DTD. This is why a feature developer needs to choose between various
* types (container element, {@link module:engine/view/attributeelement~AttributeElement attribute element},
* {@link module:engine/view/emptyelement~EmptyElement empty element}, etc) when developing a feature.
*
* Creating an element you should use `ContainerElement` class or {@link module:engine/view/attributeelement~AttributeElement}. This is
* important to define the type of the element because of two reasons:
* The container element should be your default choice when writing a converter, unless:
*
* Firstly, {@link module:engine/view/domconverter~DomConverter} needs the information what is an editable block to convert elements to
* DOM properly. {@link module:engine/view/domconverter~DomConverter} will ensure that `ContainerElement` is editable and it is possible
* to put caret inside it, even if the container is empty.
* * this element represents a model text attribute (then use {@link module:engine/view/attributeelement~AttributeElement}),
* * this is an empty element like `<img>` (then use {@link module:engine/view/emptyelement~EmptyElement}),
* * this is a root element,
* * this is a nested editable element (then use {@link module:engine/view/editableelement~EditableElement}).
*
* Secondly, {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer} uses this information.
* Nodes {@link module:engine/view/downcastwriter~DowncastWriter#breakAttributes breaking} and
* {@link module:engine/view/downcastwriter~DowncastWriter#mergeAttributes merging} is performed only in a bounds of a container nodes.
* To create a new container element instance use the
* {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement `DowncastWriter#createContainerElement()`}
* method.
*
* For instance if `<p>` is an container and `<b>` is attribute:
*
* <p><b>fo^o</b></p>
*
* {@link module:engine/view/downcastwriter~DowncastWriter#breakAttributes breakAttributes} will create:
*
* <p><b>fo</b><b>o</b></p>
*
* There might be a need to mark `<span>` element as a container node, for example in situation when it will be a
* container of an inline widget:
*
* <span color="red">foobar</span> // attribute
* <span data-widget>foobar</span> // container
*
* @extends module:engine/view/element~Element

@@ -51,4 +38,4 @@ */

*
* @see module:engine/view/downcastwriter~DowncastWriter#createContainerElement
* @see module:engine/view/element~Element
* @see module:engine/view/downcastwriter~DowncastWriter#createContainerElement
* @protected

@@ -80,6 +67,8 @@ */

// Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.
//
// @returns {Number|null} Block filler offset or `null` if block filler is not needed.
function getFillerOffset() {
/**
* Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.
*
* @returns {Number|null} Block filler offset or `null` if block filler is not needed.
*/
export function getFillerOffset() {
const children = [ ...this.getChildren() ];

@@ -86,0 +75,0 @@ const lastChild = children[ this.childCount - 1 ];

@@ -43,3 +43,3 @@ /**

* @readonly
* @member {Collection} module:engine/view/document~Document#roots
* @member {module:utils/collection~Collection} module:engine/view/document~Document#roots
*/

@@ -46,0 +46,0 @@ this.roots = new Collection( { idProperty: 'rootName' } );

@@ -17,3 +17,7 @@ /**

/**
* DocumentFragment class.
* Document fragment.
*
* To create a new document fragment instance use the
* {@link module:engine/view/upcastwriter~UpcastWriter#createDocumentFragment `UpcastWriter#createDocumentFragment()`}
* method.
*/

@@ -25,4 +29,4 @@ export default class DocumentFragment {

* @protected
* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children] List of nodes to be inserted into
* created document fragment.
* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]
* A list of nodes to be inserted into the created document fragment.
*/

@@ -29,0 +33,0 @@ constructor( children ) {

@@ -15,16 +15,10 @@ /**

/**
* 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()`}).
*/

@@ -39,15 +33,15 @@ export default class 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 );

@@ -295,15 +289,15 @@ *

* // 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 );

@@ -358,3 +352,4 @@ *

*
* 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.
*

@@ -364,3 +359,3 @@ * @protected

* @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition
* @param {Number|'end'|'before'|'after'} [offset=0] Offset or one of the flags. Used only when
* @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}.

@@ -367,0 +362,0 @@ */

@@ -537,3 +537,3 @@ /**

if ( viewElement && viewElement.is( 'uiElement' ) ) {
return ViewPosition.createBefore( viewElement );
return ViewPosition._createBefore( viewElement );
}

@@ -1070,3 +1070,3 @@

const treeWalker = new ViewTreeWalker( {
startPosition: getNext ? ViewPosition.createAfter( node ) : ViewPosition.createBefore( node ),
startPosition: getNext ? ViewPosition._createAfter( node ) : ViewPosition._createBefore( node ),
direction: getNext ? 'forward' : 'backward'

@@ -1073,0 +1073,0 @@ } );

@@ -23,2 +23,5 @@ /**

*
* The constructor of this class shouldn't be used directly. To create new `EditableElement` use the
* {@link module:engine/view/downcastwriter~DowncastWriter#createEditableElement `downcastWriter#createEditableElement()`} method.
*
* @extends module:engine/view/containerelement~ContainerElement

@@ -68,2 +71,13 @@ * @mixes module:utils/observablemixin~ObservableMixin

/**
* @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.

@@ -70,0 +84,0 @@ *

@@ -25,16 +25,17 @@ /**

*
* * {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement `writer.createContainerElement()`} in order to create
* a {@link module:engine/view/containerelement~ContainerElement},
* * {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement `writer.createAttributeElement()`} in order to create
* a {@link module:engine/view/attributeelement~AttributeElement},
* * {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement `writer.createEmptyElement()`} in order to create
* a {@link module:engine/view/emptyelement~EmptyElement}.
* * {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement `writer.createUIElement()`} in order to create
* a {@link module:engine/view/uielement~UIElement}.
* * {@link module:engine/view/downcastwriter~DowncastWriter#createEditableElement `writer.createEditableElement()`} in order to create
* a {@link module:engine/view/editableelement~EditableElement}.
* * {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement `downcastWriter#createContainerElement()`}
* in order to create a {@link module:engine/view/containerelement~ContainerElement},
* * {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement `downcastWriter#createAttributeElement()`}
* in order to create a {@link module:engine/view/attributeelement~AttributeElement},
* * {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement `downcastWriter#createEmptyElement()`}
* in order to create a {@link module:engine/view/emptyelement~EmptyElement}.
* * {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement `downcastWriter#createUIElement()`}
* in order to create a {@link module:engine/view/uielement~UIElement}.
* * {@link module:engine/view/downcastwriter~DowncastWriter#createEditableElement `downcastWriter#createEditableElement()`}
* in order to create a {@link module:engine/view/editableelement~EditableElement}.
*
* Note that for view elements which are not created from the model, like elements from mutations, paste or
* {@link module:engine/controller/datacontroller~DataController#set data.set} it is not possible to define the type of the element, so
* these will be instances of the {@link module:engine/view/element~Element}.
* {@link module:engine/controller/datacontroller~DataController#set data.set} it is not possible to define the type of the element.
* In such cases the {@link module:engine/view/upcastwriter~UpcastWriter#createElement `UpcastWriter#createElement()`} method
* should be used to create generic view elements.
*

@@ -49,13 +50,6 @@ * @extends module:engine/view/node~Node

*
* new Element( 'div', { 'class': 'editor', 'contentEditable': 'true' } ); // object
* new Element( 'div', { class: 'editor', contentEditable: 'true' } ); // object
* new Element( 'div', [ [ 'class', 'editor' ], [ 'contentEditable', 'true' ] ] ); // map-like iterator
* new Element( 'div', mapOfAttributes ); // map
*
* **Note:** Constructor of this class shouldn't be used directly in the code. Use the
* {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement} for inline element,
* {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement} for block element,
* {@link module:engine/view/downcastwriter~DowncastWriter#createEditableElement} for editable element,
* {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement} for empty element or
* {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement} for UI element instead.
*
* @protected

@@ -65,3 +59,3 @@ * @param {String} name Node name.

* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]
* List of nodes to be inserted into created element.
* A list of nodes to be inserted into created element.
*/

@@ -118,3 +112,3 @@ constructor( name, attrs, children ) {

* @protected
* @member {Set} module:engine/view/element~Element#_styles
* @member {Map} module:engine/view/element~Element#_styles
*/

@@ -134,3 +128,3 @@ this._styles = new Map();

* @protected
* @memeber {Map}
* @member {Map}
*/

@@ -582,2 +576,3 @@ this._customProperties = new Map();

* @see module:engine/view/downcastwriter~DowncastWriter#remove
* @protected
* @param {Number} index Number of the first node to remove.

@@ -684,2 +679,3 @@ * @param {Number} [howMany=1] Number of nodes to remove.

* @see module:engine/view/downcastwriter~DowncastWriter#removeClass
* @protected
* @param {Array.<String>|String} className

@@ -686,0 +682,0 @@ * @fires module:engine/view/node~Node#change

@@ -15,3 +15,8 @@ /**

/**
* EmptyElement class. It is used to represent elements that cannot contain any child nodes.
* Empty element class. It is used to represent elements that cannot contain any child nodes (for example `<img>` elements).
*
* To create a new empty element use the
* {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement `downcastWriter#createEmptyElement()`} method.
*
* @extends module:engine/view/element~Element
*/

@@ -18,0 +23,0 @@ export default class EmptyElement extends Element {

@@ -40,3 +40,3 @@ /**

/**
* `<br> filler creator. This is a function which creates `<br data-cke-filler="true">` element.
* `<br>` filler creator. This is a function which creates `<br data-cke-filler="true">` element.
* It defines how the filler is created.

@@ -43,0 +43,0 @@ *

@@ -367,3 +367,3 @@ /**

* const pattern = {
* attribute: {
* attributes: {
* title: 'foobar', // Attribute title should equal 'foobar'.

@@ -388,3 +388,3 @@ * foo: /^\w+/, // Attribute foo should match /^\w+/ regexp.

* classes: [ 'baz', 'bar', /foo.../ ]
* }:
* };
*

@@ -391,0 +391,0 @@ * // Match view element which has given styles.

@@ -19,2 +19,6 @@ /**

*
* This is an abstract class. Its constructor should not be used directly.
* Use the {@link module:engine/view/element~Element} class to create view elements
* or {@link module:engine/view/text~Text} class to create view text nodes.
*
* @abstract

@@ -25,4 +29,2 @@ */

* Creates a tree view node.
*
* This is an abstract class, so this constructor should not be used directly.
*/

@@ -128,7 +130,7 @@ constructor() {

*
* const abc = new Text( 'abc' );
* const foo = new Text( 'foo' );
* const h1 = new Element( 'h1', null, new Text( 'header' ) );
* const p = new Element( 'p', null, [ abc, foo ] );
* const div = new Element( 'div', null, [ h1, p ] );
* const abc = downcastWriter.createText( 'abc' );
* const foo = downcastWriter.createText( 'foo' );
* const h1 = downcastWriter.createElement( 'h1', null, downcastWriter.createText( 'header' ) );
* const p = downcastWriter.createElement( 'p', null, [ abc, foo ] );
* const div = downcastWriter.createElement( 'div', null, [ h1, p ] );
* foo.getPath(); // Returns [ 1, 3 ]. `foo` is in `p` which is in `div`. `p` starts at offset 1, while `foo` at 3.

@@ -263,2 +265,3 @@ * h1.getPath(); // Returns [ 0 ].

/**
* @protected
* @param {module:engine/view/document~ChangeType} type Type of the change.

@@ -265,0 +268,0 @@ * @param {module:engine/view/node~Node} node Changed node.

@@ -17,3 +17,9 @@ /**

/**
* Position in the tree. Position is always located before or after a node.
* Position in the view tree. Position is represented by its parent node and an offset in this parent.
*
* In order to create a new position instance use the `createPosition*()` factory methods available in:
*
* * {@module:engine/view/view~View}
* * {@module:engine/view/downcastwriter~DowncastWriter}
* * {@module:engine/view/upcastwriter~UpcastWriter}
*/

@@ -135,3 +141,3 @@ export default class Position {

getShiftedBy( shift ) {
const shifted = Position.createFromPosition( this );
const shifted = Position._createAt( this );

@@ -280,2 +286,21 @@ const offset = shifted.offset + shift;

/**
* 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:

@@ -290,13 +315,13 @@ *

*
* * {@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}.
*
* @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition
* @param {Number|'end'|'before'|'after'} [offset=0] Offset or one of the flags. Used only when
* @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 {

@@ -308,7 +333,15 @@ const node = itemOrPosition;

} else if ( offset == 'before' ) {
return this.createBefore( node );
return this._createBefore( node );
} else if ( offset == 'after' ) {
return this.createAfter( node );
} else if ( !offset ) {
offset = 0;
return this._createAfter( node );
} else if ( offset !== 0 && !offset ) {
/**
* {@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-createPositionAt-offset-required
*/
throw new CKEditorError(
'view-createPositionAt-offset-required: ' +
'View#createPositionAt() requires the offset when the first parameter is a view item.' );
}

@@ -323,6 +356,7 @@

*
* @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.

@@ -349,6 +383,7 @@ if ( item.is( 'textProxy' ) ) {

*
* @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.

@@ -371,12 +406,2 @@ if ( item.is( 'textProxy' ) ) {

}
/**
* 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 );
}
}

@@ -383,0 +408,0 @@

@@ -14,3 +14,9 @@ /**

/**
* Tree view range.
* Range in the view tree. A range is represented by its start and end {@link module:engine/view/position~Position positions}.
*
* In order to create a new position instance use the `createPosition*()` factory methods available in:
*
* * {@module:engine/view/view~View}
* * {@module:engine/view/downcastwriter~DowncastWriter}
* * {@module:engine/view/upcastwriter~UpcastWriter}
*/

@@ -24,3 +30,3 @@ export default class Range {

* @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.
* @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at the `start` position.
*/

@@ -34,3 +40,3 @@ constructor( start, end = null ) {

*/
this.start = Position.createFromPosition( start );
this.start = start.clone();

@@ -43,3 +49,3 @@ /**

*/
this.end = end ? Position.createFromPosition( end ) : Position.createFromPosition( start );
this.end = end ? end.clone() : start.clone();
}

@@ -98,10 +104,11 @@

*
* <p>Foo</p><p><b>{Bar}</b></p> -> <p>Foo</p>[<p><b>Bar</b>]</p>
* <p><b>foo</b>{bar}<span></span></p> -> <p><b>foo[</b>bar<span></span>]</p>
* <p>Foo</p><p><b>{Bar}</b></p> -> <p>Foo</p>[<p><b>Bar</b>]</p>
* <p><b>foo</b>{bar}<span></span></p> -> <p><b>foo[</b>bar<span></span>]</p>
*
* Note that in the sample above:
* - `<p>` have type of {@link module:engine/view/containerelement~ContainerElement},
* - `<b>` have type of {@link module:engine/view/attributeelement~AttributeElement},
* - `<span>` have type of {@link module:engine/view/uielement~UIElement}.
*
* - `<p>` have type of {@link module:engine/view/containerelement~ContainerElement},
* - `<b>` have type of {@link module:engine/view/attributeelement~AttributeElement},
* - `<span>` have type of {@link module:engine/view/uielement~UIElement}.
*
* @returns {module:engine/view/range~Range} Enlarged range.

@@ -115,7 +122,7 @@ */

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 );
}

@@ -132,10 +139,11 @@

*
* <p>Foo</p>[<p><b>Bar</b>]</p> -> <p>Foo</p><p><b>{Bar}</b></p>
* <p><b>foo[</b>bar<span></span>]</p> -> <p><b>foo</b>{bar}<span></span></p>
* <p>Foo</p>[<p><b>Bar</b>]</p> -> <p>Foo</p><p><b>{Bar}</b></p>
* <p><b>foo[</b>bar<span></span>]</p> -> <p><b>foo</b>{bar}<span></span></p>
*
* Note that in the sample above:
* - `<p>` have type of {@link module:engine/view/containerelement~ContainerElement},
* - `<b>` have type of {@link module:engine/view/attributeelement~AttributeElement},
* - `<span>` have type of {@link module:engine/view/uielement~UIElement}.
*
* - `<p>` have type of {@link module:engine/view/containerelement~ContainerElement},
* - `<b>` have type of {@link module:engine/view/attributeelement~AttributeElement},
* - `<span>` have type of {@link module:engine/view/uielement~UIElement}.
*
* @returns {module:engine/view/range~Range} Shrink range.

@@ -215,17 +223,20 @@ */

*
* let foo = new Text( 'foo' );
* let img = new ContainerElement( 'img' );
* let bar = new Text( 'bar' );
* let p = new ContainerElement( 'p', null, [ foo, img, bar ] );
* let foo = downcastWriter.createText( 'foo' );
* let img = downcastWriter.createContainerElement( 'img' );
* let bar = downcastWriter.createText( 'bar' );
* let p = downcastWriter.createContainerElement( '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 );

@@ -256,3 +267,3 @@ * // transformed array has two ranges: from ( foo, 1 ) to ( p, 1 ) and from ( p, 2 ) to ( bar, 1 )

// Ranges do not intersect, return the original range.
ranges.push( Range.createFromRange( this ) );
ranges.push( this.clone() );
}

@@ -269,12 +280,12 @@

*
* let foo = new Text( 'foo' );
* let img = new ContainerElement( 'img' );
* let bar = new Text( 'bar' );
* let p = new ContainerElement( 'p', null, [ foo, img, bar ] );
* let foo = downcastWriter.createText( 'foo' );
* let img = downcastWriter.createContainerElement( 'img' );
* let bar = downcastWriter.createText( 'bar' );
* let p = downcastWriter.createContainerElement( '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.

@@ -319,2 +330,3 @@ *

* @param {Boolean} [options.ignoreElementEnd=false]
* @returns {module:engine/view/treewalker~TreeWalker}
*/

@@ -338,2 +350,11 @@ getWalker( options = {} ) {

/**
* Clones this range.
*
* @returns {module:engine/view/range~Range}
*/
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

@@ -389,3 +410,3 @@ * them.

/**
* Checks and returns whether this range intersects with given range.
* Checks and returns whether this range intersects with the given range.
*

@@ -400,4 +421,5 @@ * @param {module:engine/view/range~Range} otherRange Range to compare with.

/**
* Creates a range from given parents and offsets.
* Creates a range from the given parents and offsets.
*
* @protected
* @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} startElement Start position

@@ -411,3 +433,3 @@ * parent element.

*/
static createFromParentsAndOffsets( startElement, startOffset, endElement, endOffset ) {
static _createFromParentsAndOffsets( startElement, startOffset, endElement, endOffset ) {
return new this(

@@ -420,15 +442,6 @@ new Position( startElement, startOffset ),

/**
* 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.

@@ -438,3 +451,3 @@ * @param {Number} shift How long the range should be.

*/
static createFromPositionAndShift( position, shift ) {
static _createFromPositionAndShift( position, shift ) {
const start = position;

@@ -450,7 +463,8 @@ const end = position.getShiftedBy( shift );

*
* @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 );
}

@@ -461,25 +475,11 @@

*
* @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 );
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=0] 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 );
}
}

@@ -486,0 +486,0 @@

@@ -6,2 +6,4 @@ /**

/* globals Node */
/**

@@ -24,2 +26,3 @@ * @module engine/view/renderer

import fastDiff from '@ckeditor/ckeditor5-utils/src/fastdiff';
import env from '@ckeditor/ckeditor5-utils/src/env';

@@ -335,3 +338,3 @@ /**

if ( firstPos.parent.is( 'text' ) ) {
return ViewPosition.createBefore( this.selection.getFirstPosition().parent );
return ViewPosition._createBefore( this.selection.getFirstPosition().parent );
} else {

@@ -758,2 +761,7 @@ return firstPos;

domSelection.extend( focus.parent, focus.offset );
// Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).
if ( env.isGecko ) {
fixGeckoSelectionAfterBr( focus, domSelection );
}
}

@@ -930,1 +938,26 @@

}
// The following is a Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).
// When the native DOM selection is at the end of the block and preceded by <br /> e.g.
//
// <p>foo<br/>[]</p>
//
// which happens a lot when using the soft line break, the browser fails to (visually) move the
// caret to the new line. A quick fix is as simple as force–refreshing the selection with the same range.
function fixGeckoSelectionAfterBr( focus, domSelection ) {
const parent = focus.parent;
// This fix works only when the focus point is at the very end of an element.
// There is no point in running it in cases unrelated to the browser bug.
if ( parent.nodeType != Node.ELEMENT_NODE || focus.offset != parent.childNodes.length - 1 ) {
return;
}
const childAtOffset = parent.childNodes[ focus.offset ];
// To stay on the safe side, the fix being as specific as possible, it targets only the
// selection which is at the very end of the element and preceded by <br />.
if ( childAtOffset && childAtOffset.tagName == 'BR' ) {
domSelection.addRange( domSelection.getRangeAt( 0 ) );
}
}

@@ -22,16 +22,12 @@ /**

/**
* 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.
*/

@@ -42,35 +38,40 @@ export default class Selection {

*
* **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' );
*

@@ -80,3 +81,3 @@ * `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 } );
*

@@ -91,3 +92,3 @@ * Fake selection does not render as browser native selection over selected elements and is hidden to the user.

* // Creates fake selection with label.
* const selection = new Selection( range, { fake: true, label: 'foo' } );
* const selection = writer.createSelection( range, { fake: true, label: 'foo' } );
*

@@ -175,3 +176,3 @@ * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection|

return Position.createFromPosition( anchor );
return anchor.clone();
}

@@ -192,3 +193,3 @@

return Position.createFromPosition( focus );
return focus.clone();
}

@@ -245,3 +246,3 @@

for ( const range of this._ranges ) {
yield Range.createFromRange( range );
yield range.clone();
}

@@ -267,3 +268,3 @@ }

return first ? Range.createFromRange( first ) : null;
return first ? first.clone() : null;
}

@@ -287,3 +288,3 @@

return last ? Range.createFromRange( last ) : null;
return last ? last.clone() : null;
}

@@ -301,3 +302,3 @@

return firstRange ? Position.createFromPosition( firstRange.start ) : null;
return firstRange ? firstRange.start.clone() : null;
}

@@ -315,3 +316,3 @@

return lastRange ? Position.createFromPosition( lastRange.end ) : null;
return lastRange ? lastRange.end.clone() : null;
}

@@ -443,11 +444,11 @@

* // 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 );

@@ -459,3 +460,3 @@ *

* // Sets collapsed selection at the given position.
* const position = new Position( root, path );
* const position = writer.createPositionAt( root, path );
* selection.setTo( position );

@@ -531,7 +532,7 @@ *

} 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 ) );
}

@@ -561,7 +562,8 @@

*
* 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
* @param {Number|'end'|'before'|'after'} [offset=0] Offset or one of the flags. Used only when
* @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}.

@@ -581,3 +583,3 @@ */

const newFocus = Position.createAt( itemOrPosition, offset );
const newFocus = Position._createAt( itemOrPosition, offset );

@@ -703,3 +705,3 @@ if ( newFocus.compareWith( this.focus ) == 'same' ) {

this._ranges.push( Range.createFromRange( range ) );
this._ranges.push( new Range( range.start, range.end ) );
}

@@ -706,0 +708,0 @@

@@ -15,2 +15,8 @@ /**

*
* The constructor of this class shouldn't be used directly. To create new Text instances
* use the {@link module:engine/view/downcastwriter~DowncastWriter#createText `DowncastWriter#createText()`}
* method when working on data downcasted from the model or the
* {@link module:engine/view/upcastwriter~UpcastWriter#createText `UpcastWriter#createText()`}
* method when working on non-semantic views.
*
* @extends module:engine/view/node~Node

@@ -22,7 +28,4 @@ */

*
* **Note:** Constructor of this class shouldn't be used directly in the code.
* Use the {@link module:engine/view/downcastwriter~DowncastWriter#createText} method instead.
*
* @protected
* @param {String} data Text.
* @param {String} data The text's data.
*/

@@ -53,3 +56,4 @@ constructor( data ) {

*
* @returns {String}
* @readonly
* @type {String}
*/

@@ -63,4 +67,4 @@ get data() {

*
* const foo = new Text( 'foo' );
* const bar = new Text( 'bar' );
* const foo = downcastWriter.createText( 'foo' );
* const bar = downcastWriter.createText( 'bar' );
*

@@ -73,3 +77,3 @@ * foo._data += bar.data; // executes: `foo._data = foo._data + bar.data`

* @protected
* @returns {String}
* @type {String}
*/

@@ -76,0 +80,0 @@ get _data() {

@@ -88,3 +88,6 @@ /**

/**
* @inheritDoc
* Offset size of this node.
*
* @readonly
* @type {Number}
*/

@@ -91,0 +94,0 @@ get offsetSize() {

@@ -76,5 +76,5 @@ /**

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' ] );
}

@@ -193,3 +193,3 @@

_next() {
let position = Position.createFromPosition( this.position );
let position = this.position.clone();
const previousPosition = this.position;

@@ -215,3 +215,3 @@ const parent = position.parent;

// 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 );

@@ -250,3 +250,3 @@ return this._next();

item = new TextProxy( node, 0, charactersCount );
position = Position.createAfter( item );
position = Position._createAfter( item );
} else {

@@ -282,3 +282,3 @@ item = new TextProxy( node, 0, node.data.length );

// `node` is not set, we reached the end of current `parent`.
position = Position.createAfter( parent );
position = Position._createAfter( parent );
this.position = position;

@@ -303,3 +303,3 @@

_previous() {
let position = Position.createFromPosition( this.position );
let position = this.position.clone();
const previousPosition = this.position;

@@ -325,3 +325,3 @@ const parent = position.parent;

// 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 );

@@ -368,3 +368,3 @@ return this._previous();

charactersCount = item.data.length;
position = Position.createBefore( item );
position = Position._createBefore( item );
} else {

@@ -401,3 +401,3 @@ item = new TextProxy( node, 0, node.data.length );

// `node` is not set, we reached the beginning of current `parent`.
position = Position.createBefore( parent );
position = Position._createBefore( parent );
this.position = position;

@@ -429,7 +429,7 @@

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 );
}

@@ -441,7 +441,7 @@ }

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 );
}

@@ -478,11 +478,11 @@ }

* @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.

@@ -494,5 +494,5 @@ * * Forward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is

* * 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`.
*/

@@ -499,0 +499,0 @@

@@ -16,4 +16,20 @@ /**

/**
* UIElement class. It is used to represent UI not a content of the document.
* This element can't be split and selection can't be placed inside this element.
* UI element class. It should be used to represent editing UI which needs to be injected into the editing view
* If possible, you should keep your UI outside the editing view. However, if that is not possible,
* UI elements can be used.
*
* How a UI element is rendered is in your control (you pass a callback to
* {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement `downcastWriter#createUIElement()`}).
* The editor will ignore your UI element – the selection cannot be placed in it, it is skipped (invisible) when
* the user modifies the selection by using arrow keys and the editor does not listen to any mutations which
* happen inside your UI elements.
*
* The limitation is that you cannot convert a model element to a UI element. UI elements need to be
* created for {@link module:engine/model/markercollection~Marker markers} or as additinal elements
* inside normal {@link module:engine/view/containerelement~ContainerElement container elements}.
*
* To create a new UI element use the
* {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement `downcastWriter#createUIElement()`} method.
*
* @extends module:engine/view/element~Element
*/

@@ -76,3 +92,3 @@ export default class UIElement extends Element {

*
* const myUIElement = new UIElement( 'span' );
* const myUIElement = downcastWriter.createUIElement( 'span' );
* myUIElement.render = function( domDocument ) {

@@ -79,0 +95,0 @@ * const domElement = this.toDomElement( domDocument );

@@ -10,15 +10,73 @@ /**

import DocumentFragment from './documentfragment';
import Element from './element';
import Text from './text';
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 non-semantic view trees.
*
* 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}.
*
* Read more about changing the view in the {@glink framework/guides/architecture/editing-engine#changing-the-view Changing the view}
* section of the {@glink framework/guides/architecture/editing-engine Editing engine architecture} guide.
*
* Unlike `DowncastWriter`, which is available in the {@link module:engine/view/view~View#change `View#change()`} block,
* `UpcastWriter` can wherever you need it:
*
* const writer = new UpcastWriter();
* const text = writer.createText( 'foo!' );
*
* writer.appendChild( text, someViewElement );
*/
export default class UpcastWriter {
/**
* Clones provided element.
* Creates a new {@link module:engine/view/documentfragment~DocumentFragment} instance.
*
* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]
* A list of nodes to be inserted into the created document fragment.
* @returns {module:engine/view/documentfragment~DocumentFragment} The created document fragment.
*/
createDocumentFragment( children ) {
return new DocumentFragment( children );
}
/**
* Creates a new {@link module:engine/view/element~Element} instance.
*
* Attributes can be passed in various formats:
*
* upcastWriter.createElement( 'div', { class: 'editor', contentEditable: 'true' } ); // object
* upcastWriter.createElement( 'div', [ [ 'class', 'editor' ], [ 'contentEditable', 'true' ] ] ); // map-like iterator
* upcastWriter.createElement( 'div', mapOfAttributes ); // map
*
* @param {String} name Node name.
* @param {Object|Iterable} [attrs] Collection of attributes.
* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]
* A list of nodes to be inserted into created element.
* @returns {module:engine/view/element~Element} Created element.
*/
createElement( name, attrs, children ) {
return new Element( name, attrs, children );
}
/**
* Creates a new {@link module:engine/view/text~Text} instance.
*
* @param {String} data The text's data.
* @returns {module:engine/view/text~Text} The created text node.
*/
createText( data ) {
return new Text( data );
}
/**
* Clones the provided element.
*
* @see module:engine/view/element~Element#_clone

@@ -66,3 +124,3 @@ * @param {module:engine/view/element~Element} element Element to be cloned.

/**
* 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`.
*

@@ -250,2 +308,143 @@ * @see module:engine/view/element~Element#_removeChildren

}
/**
* 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/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 );
}
}

@@ -14,2 +14,5 @@ /**

import DomConverter from './domconverter';
import Position from './position';
import Range from './range';
import Selection from './selection';

@@ -54,6 +57,6 @@ import MutationObserver from './observer/mutationobserver';

*
* This class also {@link module:engine/view/view~View#attachDomRoot bind DOM and View elements}.
* This class also {@link module:engine/view/view~View#attachDomRoot binds the DOM and the view elements}.
*
* If you do not need full DOM - View management, and want to only transform the tree of view elements to the DOM
* elements you do not need this controller, you can use the {@link module:engine/view/domconverter~DomConverter DomConverter}.
* If you do not need full a DOM - view management, and only want to transform a tree of view elements to a tree of DOM
* elements you do not need this controller. You can use the {@link module:engine/view/domconverter~DomConverter DomConverter} instead.
*

@@ -310,9 +313,10 @@ * @mixes module:utils/observablemixin~ObservableMixin

/**
* Change method is the primary way of changing the view. You should use it to modify any node in the view tree.
* It makes sure that after all changes are made view is rendered to DOM. It prevents situations when DOM is updated
* when view state is not yet correct. It allows to nest calls one inside another and still perform single rendering
* after all changes are applied.
* The `change()` method is the primary way of changing the view. You should use it to modify any node in the view tree.
* It makes sure that after all changes are made the view is rendered to the DOM. It prevents situations when the DOM is updated
* when the view state is not yet correct. It allows to nest calls one inside another and still performs a single rendering
* after all those changes are made. It also returns the return value of its callback.
*
* view.change( writer => {
* writer.insert( position1, writer.createText( 'foo' ) );
* const text = view.change( writer => {
* const newText = writer.createText( 'foo' );
* writer.insert( position1, newText );
*

@@ -324,13 +328,14 @@ * view.change( writer => {

* writer.remove( range );
*
* return newText;
* } );
*
* Change block is executed immediately.
* When the outermost change block is done and rendering to the DOM is over the
* {@link module:engine/view/view~View#event:render `View#render`} event is fired.
*
* When the outermost change block is done and rendering to DOM is over it fires
* {@link module:engine/view/view~View#event:render} event.
* This method throws a `applying-view-changes-on-rendering` error when
* the change block is used after rendering to the DOM has started.
*
* Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `applying-view-changes-on-rendering` when
* change block is used after rendering to DOM has started.
*
* @param {Function} callback Callback function which may modify the view.
* @returns {*} Value returned by the callback.
*/

@@ -347,7 +352,9 @@ change( callback ) {

* {@link module:engine/view/document~Document#registerPostFixer post-fixer function}.
*
* @error cannot-change-view-tree
*/
throw new CKEditorError(
'cannot-change-view-tree: ' +
'Attempting to make changes to the view when it is in incorrect state: rendering or post-fixers are in progress. ' +
'This may cause some unexpected behaviour and inconsistency between the DOM and the view.'
'Attempting to make changes to the view when it is in an incorrect state: rendering or post-fixers are in progress. ' +
'This may cause some unexpected behavior and inconsistency between the DOM and the view.'
);

@@ -358,5 +365,3 @@ }

if ( this._ongoingChange ) {
callback( this._writer );
return;
return callback( this._writer );
}

@@ -367,3 +372,3 @@

this._ongoingChange = true;
callback( this._writer );
const callbackResult = callback( this._writer );
this._ongoingChange = false;

@@ -380,2 +385,4 @@

}
return callbackResult;
}

@@ -406,2 +413,143 @@

/**
* 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/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

@@ -408,0 +556,0 @@ * before rendering and re-enabled after that.

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc