Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
offset = offset < 0 ? 0 : offset;
}
return new ViewPosition( viewParent, offset );
}
// domParent instanceof HTMLElement.
else {
if ( domOffset === 0 ) {
const viewParent = this.mapDomToView( domParent );
if ( viewParent ) {
return new ViewPosition( viewParent, 0 );
}
} else {
const domBefore = domParent.childNodes[ domOffset - 1 ];
const viewBefore = isText( domBefore ) ?
this.findCorrespondingViewText( domBefore ) :
this.mapDomToView( domBefore );
// TODO #663
if ( viewBefore && viewBefore.parent ) {
return new ViewPosition( viewBefore.parent, viewBefore.index + 1 );
}
}
return null;
}
}
return false;
}
// Note, we can't check if selection's position equals position of the
// this._inlineFiller node, because of #663. We may not be able to calculate
// the filler's position in the view at this stage.
// Instead, we check it the other way – whether selection is anchored in
// that text node or next to it.
// Possible options are:
// "FILLER{}"
// "FILLERadded-text{}"
const selectionPosition = this.selection.getFirstPosition();
const position = this.domConverter.viewPositionToDom( selectionPosition );
if ( position && isText( position.parent ) && startsWithFiller( position.parent ) ) {
return true;
}
return false;
}
domBefore = nodeBefore.is( 'text' ) ?
this.findCorrespondingDomText( nodeBefore ) :
this.mapViewToDom( viewPosition.nodeBefore );
if ( !domBefore ) {
// Position is after a view element that has not been rendered to DOM yet.
return null;
}
domParent = domBefore.parentNode;
domAfter = domBefore.nextSibling;
}
// If there is an inline filler at position return position inside the filler. We should never return
// the position before the inline filler.
if ( isText( domAfter ) && startsWithFiller( domAfter ) ) {
return { parent: domAfter, offset: INLINE_FILLER_LENGTH };
}
const offset = domBefore ? indexOf( domBefore ) + 1 : 0;
return { parent: domParent, offset };
}
}
domPositionToView( domParent, domOffset ) {
if ( this.isBlockFiller( domParent, this.blockFillerMode ) ) {
return this.domPositionToView( domParent.parentNode, indexOf( domParent ) );
}
// If position is somewhere inside UIElement - return position before that element.
const viewElement = this.mapDomToView( domParent );
if ( viewElement && viewElement.is( 'uiElement' ) ) {
return ViewPosition._createBefore( viewElement );
}
if ( isText( domParent ) ) {
if ( isInlineFiller( domParent ) ) {
return this.domPositionToView( domParent.parentNode, indexOf( domParent ) );
}
const viewParent = this.findCorrespondingViewText( domParent );
let offset = domOffset;
if ( !viewParent ) {
return null;
}
if ( startsWithFiller( domParent ) ) {
offset -= INLINE_FILLER_LENGTH;
offset = offset < 0 ? 0 : offset;
}
domSelectionToView( domSelection ) {
// DOM selection might be placed in fake selection container.
// If container contains fake selection - return corresponding view selection.
if ( domSelection.rangeCount === 1 ) {
let container = domSelection.getRangeAt( 0 ).startContainer;
// The DOM selection might be moved to the text node inside the fake selection container.
if ( isText( container ) ) {
container = container.parentNode;
}
const viewSelection = this.fakeSelectionToView( container );
if ( viewSelection ) {
return viewSelection;
}
}
const isBackward = this.isDomSelectionBackward( domSelection );
const viewRanges = [];
for ( let i = 0; i < domSelection.rangeCount; i++ ) {
// DOM Range have correct start and end, no matter what is the DOM Selection direction. So we don't have to fix anything.
function addInlineFiller( domDocument, domParentOrArray, offset ) {
const childNodes = domParentOrArray instanceof Array ? domParentOrArray : domParentOrArray.childNodes;
const nodeAfterFiller = childNodes[ offset ];
if ( isText( nodeAfterFiller ) ) {
nodeAfterFiller.data = INLINE_FILLER + nodeAfterFiller.data;
return nodeAfterFiller;
} else {
const fillerNode = domDocument.createTextNode( INLINE_FILLER );
if ( Array.isArray( domParentOrArray ) ) {
childNodes.splice( offset, 0, fillerNode );
} else {
insertAt( domParentOrArray, offset, fillerNode );
}
return fillerNode;
}
}
function isNbspBlockFiller( domNode, blockElements ) {
const isNBSP = isText( domNode ) && domNode.data == '\u00A0';
return isNBSP && hasBlockParent( domNode, blockElements ) && domNode.parentNode.childNodes.length === 1;
}
function areSimilar( node1, node2 ) {
return isNode( node1 ) && isNode( node2 ) &&
!isText( node1 ) && !isText( node2 ) &&
node1.tagName.toLowerCase() === node2.tagName.toLowerCase();
}