Skip to content

Commit

Permalink
Try consolidating some of the copy and paste behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewserong committed Jan 24, 2024
1 parent 68ed6c7 commit 885b147
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 160 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
/**
* WordPress dependencies
*/
import {
serialize,
pasteHandler,
createBlock,
findTransform,
getBlockTransforms,
} from '@wordpress/blocks';
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
import { useDispatch, useSelect } from '@wordpress/data';
import { useRefEffect } from '@wordpress/compose';

/**
* Internal dependencies
*/
import { getPasteEventData } from '../../utils/pasting';
import { store as blockEditorStore } from '../../store';
import { useNotifyCopy } from '../../utils/use-notify-copy';
import { focusListItem } from './utils';
import { getPasteBlocks, setClipboardBlocks } from '../writing-flow/utils';

export default function useClipboardHandler( { selectBlock } ) {
const {
Expand Down Expand Up @@ -111,33 +103,8 @@ export default function useClipboardHandler( { selectBlock } ) {
}

notifyCopy( event.type, selectedBlockClientIds );
let blocks;
// Check if we have partial selection.
blocks = getBlocksByClientId( selectedBlockClientIds );

const wrapperBlockName = event.clipboardData.getData(
'__unstableWrapperBlockName'
);

if ( wrapperBlockName ) {
blocks = createBlock(
wrapperBlockName,
JSON.parse(
event.clipboardData.getData(
'__unstableWrapperBlockAttributes'
)
),
blocks
);
}

const serialized = serialize( blocks );

event.clipboardData.setData(
'text/plain',
toPlainText( serialized )
);
event.clipboardData.setData( 'text/html', serialized );
const blocks = getBlocksByClientId( selectedBlockClientIds );
setClipboardBlocks( event, blocks );
}

if ( event.type === 'cut' ) {
Expand Down Expand Up @@ -176,35 +143,10 @@ export default function useClipboardHandler( { selectBlock } ) {
__experimentalCanUserUseUnfilteredHTML:
canUserUseUnfilteredHTML,
} = getSettings();
const { plainText, html, files } = getPasteEventData( event );
let blocks = [];

if ( files.length ) {
const fromTransforms = getBlockTransforms( 'from' );
blocks = files
.reduce( ( accumulator, file ) => {
const transformation = findTransform(
fromTransforms,
( transform ) =>
transform.type === 'files' &&
transform.isMatch( [ file ] )
);
if ( transformation ) {
accumulator.push(
transformation.transform( [ file ] )
);
}
return accumulator;
}, [] )
.flat();
} else {
blocks = pasteHandler( {
HTML: html,
plainText,
mode: 'BLOCKS',
canUserUseUnfilteredHTML,
} );
}
const blocks = getPasteBlocks(
event,
canUserUseUnfilteredHTML
);

if ( selectedBlockClientIds.length === 1 ) {
const [ selectedBlockClientId ] = selectedBlockClientIds;
Expand Down Expand Up @@ -253,20 +195,3 @@ export default function useClipboardHandler( { selectBlock } ) {
};
}, [] );
}

/**
* Given a string of HTML representing serialized blocks, returns the plain
* text extracted after stripping the HTML of any tags and fixing line breaks.
*
* @param {string} html Serialized blocks.
* @return {string} The plain-text content with any html removed.
*/
function toPlainText( html ) {
// Manually handle BR tags as line breaks prior to `stripHTML` call
html = html.replace( /<br>/g, '\n' );

const plainText = stripHTML( html ).trim();

// Merge any consecutive line breaks
return plainText.replace( /\n\n+/g, '\n\n' );
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
/**
* WordPress dependencies
*/
import {
serialize,
pasteHandler,
createBlock,
findTransform,
getBlockTransforms,
} from '@wordpress/blocks';
import {
documentHasSelection,
documentHasUncollapsedSelection,
__unstableStripHTML as stripHTML,
} from '@wordpress/dom';
import { useDispatch, useSelect } from '@wordpress/data';
import { useRefEffect } from '@wordpress/compose';

/**
* Internal dependencies
*/
import { getPasteEventData } from '../../utils/pasting';
import { store as blockEditorStore } from '../../store';
import { useNotifyCopy } from '../../utils/use-notify-copy';
import { getPasteBlocks, setClipboardBlocks } from './utils';

export default function useClipboardHandler() {
const {
Expand Down Expand Up @@ -112,29 +104,7 @@ export default function useClipboardHandler() {
blocks = [ head, ...inBetweenBlocks, tail ];
}

const wrapperBlockName = event.clipboardData.getData(
'__unstableWrapperBlockName'
);

if ( wrapperBlockName ) {
blocks = createBlock(
wrapperBlockName,
JSON.parse(
event.clipboardData.getData(
'__unstableWrapperBlockAttributes'
)
),
blocks
);
}

const serialized = serialize( blocks );

event.clipboardData.setData(
'text/plain',
toPlainText( serialized )
);
event.clipboardData.setData( 'text/html', serialized );
setClipboardBlocks( event, blocks );
}
}

Expand All @@ -153,35 +123,10 @@ export default function useClipboardHandler() {
__experimentalCanUserUseUnfilteredHTML:
canUserUseUnfilteredHTML,
} = getSettings();
const { plainText, html, files } = getPasteEventData( event );
let blocks = [];

if ( files.length ) {
const fromTransforms = getBlockTransforms( 'from' );
blocks = files
.reduce( ( accumulator, file ) => {
const transformation = findTransform(
fromTransforms,
( transform ) =>
transform.type === 'files' &&
transform.isMatch( [ file ] )
);
if ( transformation ) {
accumulator.push(
transformation.transform( [ file ] )
);
}
return accumulator;
}, [] )
.flat();
} else {
blocks = pasteHandler( {
HTML: html,
plainText,
mode: 'BLOCKS',
canUserUseUnfilteredHTML,
} );
}
const blocks = getPasteBlocks(
event,
canUserUseUnfilteredHTML
);

if ( selectedBlockClientIds.length === 1 ) {
const [ selectedBlockClientId ] = selectedBlockClientIds;
Expand Down Expand Up @@ -223,20 +168,3 @@ export default function useClipboardHandler() {
};
}, [] );
}

/**
* Given a string of HTML representing serialized blocks, returns the plain
* text extracted after stripping the HTML of any tags and fixing line breaks.
*
* @param {string} html Serialized blocks.
* @return {string} The plain-text content with any html removed.
*/
function toPlainText( html ) {
// Manually handle BR tags as line breaks prior to `stripHTML` call
html = html.replace( /<br>/g, '\n' );

const plainText = stripHTML( html ).trim();

// Merge any consecutive line breaks
return plainText.replace( /\n\n+/g, '\n\n' );
}
89 changes: 89 additions & 0 deletions packages/block-editor/src/components/writing-flow/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* WordPress dependencies
*/
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
import {
serialize,
createBlock,
pasteHandler,
findTransform,
getBlockTransforms,
} from '@wordpress/blocks';

/**
* Internal dependencies
*/
import { getPasteEventData } from '../../utils/pasting';

export function setClipboardBlocks( event, blocks ) {
let _blocks = blocks;
const wrapperBlockName = event.clipboardData.getData(
'__unstableWrapperBlockName'
);

if ( wrapperBlockName ) {
_blocks = createBlock(
wrapperBlockName,
JSON.parse(
event.clipboardData.getData(
'__unstableWrapperBlockAttributes'
)
),
_blocks
);
}

const serialized = serialize( _blocks );

event.clipboardData.setData( 'text/plain', toPlainText( serialized ) );
event.clipboardData.setData( 'text/html', serialized );
}

export function getPasteBlocks( event, canUserUseUnfilteredHTML ) {
const { plainText, html, files } = getPasteEventData( event );
let blocks = [];

if ( files.length ) {
const fromTransforms = getBlockTransforms( 'from' );
blocks = files
.reduce( ( accumulator, file ) => {
const transformation = findTransform(
fromTransforms,
( transform ) =>
transform.type === 'files' &&
transform.isMatch( [ file ] )
);
if ( transformation ) {
accumulator.push( transformation.transform( [ file ] ) );
}
return accumulator;
}, [] )
.flat();
} else {
blocks = pasteHandler( {
HTML: html,
plainText,
mode: 'BLOCKS',
canUserUseUnfilteredHTML,
} );
}

return blocks;
}

/**
* Given a string of HTML representing serialized blocks, returns the plain
* text extracted after stripping the HTML of any tags and fixing line breaks.
*
* @param {string} html Serialized blocks.
* @return {string} The plain-text content with any html removed.
*/
function toPlainText( html ) {
// Manually handle BR tags as line breaks prior to `stripHTML` call
html = html.replace( /<br>/g, '\n' );

const plainText = stripHTML( html ).trim();

// Merge any consecutive line breaks
return plainText.replace( /\n\n+/g, '\n\n' );
}

0 comments on commit 885b147

Please sign in to comment.