0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2024-12-22 15:23:29 -05:00

Preserve target block formatting when pasting inline text

If you have a document like this:

<div style="font-size:20px">XXXX</div>
<div style="font-size:14px">YYYY</div>

and you select the YYYY text and copy it, we just copy the text to the clipboard
and not the block formatting. This is fine.

Now you select XXXX and paste. Because that removes all content from the first
block we were replacing it with the block formatting from the clipboard. But
this has no block formatting, so you essentially just "lost" the font-size:20px,
which broke user expectations.

(If the copied text *did* have block formatting, then replacing the block is
the correct thing to do in this case, which we still do.)
This commit is contained in:
Neil Jenkins 2020-02-24 14:43:40 +11:00
parent 2799f172ee
commit c5a7c622fe
3 changed files with 21 additions and 7 deletions

View file

@ -919,6 +919,7 @@ var deleteContentsOfRange = function ( range, root ) {
// Contents of range will be deleted. // Contents of range will be deleted.
// After method, range will be around inserted content // After method, range will be around inserted content
var insertTreeFragmentIntoRange = function ( range, frag, root ) { var insertTreeFragmentIntoRange = function ( range, frag, root ) {
var firstInFragIsInline = frag.firstChild && isInline( frag.firstChild );
var node, block, blockContentsAfterSplit, stopPoint, container, offset; var node, block, blockContentsAfterSplit, stopPoint, container, offset;
var replaceBlock, firstBlockInFrag, nodeAfterSplit, nodeBeforeSplit; var replaceBlock, firstBlockInFrag, nodeAfterSplit, nodeBeforeSplit;
var tempRange; var tempRange;
@ -944,11 +945,17 @@ var insertTreeFragmentIntoRange = function ( range, frag, root ) {
// Merge the contents of the first block in the frag with the focused block. // Merge the contents of the first block in the frag with the focused block.
// If there are contents in the block after the focus point, collect this // If there are contents in the block after the focus point, collect this
// up to insert in the last block later. If the block is empty, replace // up to insert in the last block later. This preserves the style that was
// it instead of merging. // present in this bit of the page.
//
// If the block being inserted into is empty though, replace it instead of
// merging if the fragment had block contents.
// e.g. <blockquote><p>Foo</p></blockquote>
// This seems a reasonable approximation of user intent.
block = getStartBlockOfRange( range, root ); block = getStartBlockOfRange( range, root );
firstBlockInFrag = getNextBlock( frag, frag ); firstBlockInFrag = getNextBlock( frag, frag );
replaceBlock = !!block && isEmptyBlock( block ); replaceBlock = !firstInFragIsInline && !!block && isEmptyBlock( block );
if ( block && firstBlockInFrag && !replaceBlock && if ( block && firstBlockInFrag && !replaceBlock &&
// Don't merge table cells or PRE elements into block // Don't merge table cells or PRE elements into block
!getNearest( firstBlockInFrag, frag, 'PRE' ) && !getNearest( firstBlockInFrag, frag, 'PRE' ) &&

File diff suppressed because one or more lines are too long

View file

@ -189,6 +189,7 @@ var deleteContentsOfRange = function ( range, root ) {
// Contents of range will be deleted. // Contents of range will be deleted.
// After method, range will be around inserted content // After method, range will be around inserted content
var insertTreeFragmentIntoRange = function ( range, frag, root ) { var insertTreeFragmentIntoRange = function ( range, frag, root ) {
var firstInFragIsInline = frag.firstChild && isInline( frag.firstChild );
var node, block, blockContentsAfterSplit, stopPoint, container, offset; var node, block, blockContentsAfterSplit, stopPoint, container, offset;
var replaceBlock, firstBlockInFrag, nodeAfterSplit, nodeBeforeSplit; var replaceBlock, firstBlockInFrag, nodeAfterSplit, nodeBeforeSplit;
var tempRange; var tempRange;
@ -214,11 +215,17 @@ var insertTreeFragmentIntoRange = function ( range, frag, root ) {
// Merge the contents of the first block in the frag with the focused block. // Merge the contents of the first block in the frag with the focused block.
// If there are contents in the block after the focus point, collect this // If there are contents in the block after the focus point, collect this
// up to insert in the last block later. If the block is empty, replace // up to insert in the last block later. This preserves the style that was
// it instead of merging. // present in this bit of the page.
//
// If the block being inserted into is empty though, replace it instead of
// merging if the fragment had block contents.
// e.g. <blockquote><p>Foo</p></blockquote>
// This seems a reasonable approximation of user intent.
block = getStartBlockOfRange( range, root ); block = getStartBlockOfRange( range, root );
firstBlockInFrag = getNextBlock( frag, frag ); firstBlockInFrag = getNextBlock( frag, frag );
replaceBlock = !!block && isEmptyBlock( block ); replaceBlock = !firstInFragIsInline && !!block && isEmptyBlock( block );
if ( block && firstBlockInFrag && !replaceBlock && if ( block && firstBlockInFrag && !replaceBlock &&
// Don't merge table cells or PRE elements into block // Don't merge table cells or PRE elements into block
!getNearest( firstBlockInFrag, frag, 'PRE' ) && !getNearest( firstBlockInFrag, frag, 'PRE' ) &&