mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 15:23:29 -05:00
When inserting text nodes, merge them with text nodes that border it.
This fixes a bug where if you paste two text nodes in a row, an error occurs.
This commit is contained in:
parent
dfed911833
commit
4ee0b7ea87
4 changed files with 129 additions and 3 deletions
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
all: install build
|
all: install build
|
||||||
|
|
||||||
intall:
|
install:
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -687,15 +687,78 @@ var insertNodeInRange = function ( range, node ) {
|
||||||
|
|
||||||
childCount = children.length;
|
childCount = children.length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge the given text node and the one on its left together into one text node.
|
||||||
|
*/
|
||||||
|
var mergeLeft = function ( node ) {
|
||||||
|
if ( node.nodeType !== TEXT_NODE ) return;
|
||||||
|
var prev = node.previousSibling;
|
||||||
|
if ( prev && prev.nodeType === TEXT_NODE ) {
|
||||||
|
// Update the end of the selection if it'll be affected by our merge
|
||||||
|
var prevIndex = indexOf.call( endContainer.childNodes, prev );
|
||||||
|
if ( prevIndex >= 0 ) {
|
||||||
|
if ( prevIndex <= endOffset ) {
|
||||||
|
endOffset--;
|
||||||
|
} else if ( prevIndex + 1 === endOffset ) {
|
||||||
|
// It ends between the nodes we're merging. So find the index into that node.
|
||||||
|
endContainer = prev;
|
||||||
|
endOffset = prev.data.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( endContainer === prev ) {
|
||||||
|
endOffset += node.data.length;
|
||||||
|
}
|
||||||
|
// The updated selection will start in the middle of the previous element now.
|
||||||
|
startContainer = prev;
|
||||||
|
startOffset = prev.data.length;
|
||||||
|
|
||||||
|
prev.appendData( node.data );
|
||||||
|
node.parentNode.removeChild( node );
|
||||||
|
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge the given text node and the one on its right together into one text node.
|
||||||
|
*/
|
||||||
|
var mergeRight = function ( node ) {
|
||||||
|
if ( node.nodeType !== TEXT_NODE ) return;
|
||||||
|
var next = node.nextSibling;
|
||||||
|
if ( next && next.nodeType === TEXT_NODE ) {
|
||||||
|
var nextIndex = indexOf.call( endContainer.childNodes, next );
|
||||||
|
if ( nextIndex >= 0 ) {
|
||||||
|
if ( nextIndex <= endOffset ) {
|
||||||
|
endOffset--;
|
||||||
|
} else if ( nextIndex + 1 === endOffset ) {
|
||||||
|
// It ends between the nodes we're merging. So find the index into that node.
|
||||||
|
endContainer = next;
|
||||||
|
endOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( endContainer === next ) {
|
||||||
|
endContainer = node;
|
||||||
|
endOffset += node.data.length;
|
||||||
|
}
|
||||||
|
node.appendData( next.data );
|
||||||
|
next.parentNode.removeChild( next );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( startOffset === childCount) {
|
if ( startOffset === childCount) {
|
||||||
startContainer.appendChild( node );
|
startContainer.appendChild( node );
|
||||||
} else {
|
} else {
|
||||||
startContainer.insertBefore( node, children[ startOffset ] );
|
startContainer.insertBefore( node, children[ startOffset ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( startContainer === endContainer ) {
|
if ( startContainer === endContainer ) {
|
||||||
endOffset += children.length - childCount;
|
endOffset += children.length - childCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we split a text node, merge the text nodes back together
|
||||||
|
var insertedNode = children[ startOffset ];
|
||||||
|
mergeRight( mergeLeft( insertedNode ) || insertedNode );
|
||||||
|
|
||||||
range.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
range.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -103,15 +103,78 @@ var insertNodeInRange = function ( range, node ) {
|
||||||
|
|
||||||
childCount = children.length;
|
childCount = children.length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge the given text node and the one on its left together into one text node.
|
||||||
|
*/
|
||||||
|
var mergeLeft = function ( node ) {
|
||||||
|
if ( node.nodeType !== TEXT_NODE ) return;
|
||||||
|
var prev = node.previousSibling;
|
||||||
|
if ( prev && prev.nodeType === TEXT_NODE ) {
|
||||||
|
// Update the end of the selection if it'll be affected by our merge
|
||||||
|
var prevIndex = indexOf.call( endContainer.childNodes, prev );
|
||||||
|
if ( prevIndex >= 0 ) {
|
||||||
|
if ( prevIndex <= endOffset ) {
|
||||||
|
endOffset--;
|
||||||
|
} else if ( prevIndex + 1 === endOffset ) {
|
||||||
|
// It ends between the nodes we're merging. So find the index into that node.
|
||||||
|
endContainer = prev;
|
||||||
|
endOffset = prev.data.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( endContainer === prev ) {
|
||||||
|
endOffset += node.data.length;
|
||||||
|
}
|
||||||
|
// The updated selection will start in the middle of the previous element now.
|
||||||
|
startContainer = prev;
|
||||||
|
startOffset = prev.data.length;
|
||||||
|
|
||||||
|
prev.appendData( node.data );
|
||||||
|
node.parentNode.removeChild( node );
|
||||||
|
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge the given text node and the one on its right together into one text node.
|
||||||
|
*/
|
||||||
|
var mergeRight = function ( node ) {
|
||||||
|
if ( node.nodeType !== TEXT_NODE ) return;
|
||||||
|
var next = node.nextSibling;
|
||||||
|
if ( next && next.nodeType === TEXT_NODE ) {
|
||||||
|
var nextIndex = indexOf.call( endContainer.childNodes, next );
|
||||||
|
if ( nextIndex >= 0 ) {
|
||||||
|
if ( nextIndex <= endOffset ) {
|
||||||
|
endOffset--;
|
||||||
|
} else if ( nextIndex + 1 === endOffset ) {
|
||||||
|
// It ends between the nodes we're merging. So find the index into that node.
|
||||||
|
endContainer = next;
|
||||||
|
endOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( endContainer === next ) {
|
||||||
|
endContainer = node;
|
||||||
|
endOffset += node.data.length;
|
||||||
|
}
|
||||||
|
node.appendData( next.data );
|
||||||
|
next.parentNode.removeChild( next );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( startOffset === childCount) {
|
if ( startOffset === childCount) {
|
||||||
startContainer.appendChild( node );
|
startContainer.appendChild( node );
|
||||||
} else {
|
} else {
|
||||||
startContainer.insertBefore( node, children[ startOffset ] );
|
startContainer.insertBefore( node, children[ startOffset ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( startContainer === endContainer ) {
|
if ( startContainer === endContainer ) {
|
||||||
endOffset += children.length - childCount;
|
endOffset += children.length - childCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we split a text node, merge the text nodes back together
|
||||||
|
var insertedNode = children[ startOffset ];
|
||||||
|
mergeRight( mergeLeft( insertedNode ) || insertedNode );
|
||||||
|
|
||||||
range.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
range.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue