From 802c73c51f3459281f411e0fd7c0c4dc6b18cf37 Mon Sep 17 00:00:00 2001 From: Mikhaela Tapia <98727316+mxkae@users.noreply.github.com> Date: Sat, 13 Jul 2024 23:14:37 +0800 Subject: [PATCH] fix (WP 6.6): icon list on paste (#3230) * remove unused useCopy * add onPaste * fix on paste for lists from ms word and gdocs * update onPaste --- src/block/icon-list-item/edit.js | 3 ++ src/block/icon-list-item/util.js | 80 ++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/src/block/icon-list-item/edit.js b/src/block/icon-list-item/edit.js index 3f899ec86..ab692cf2e 100644 --- a/src/block/icon-list-item/edit.js +++ b/src/block/icon-list-item/edit.js @@ -6,6 +6,7 @@ import { getUseSvgDef } from '../icon-list/util' import { convertToListItems, useOnSplit, + useOnPaste, useEnter, } from './util' @@ -95,6 +96,7 @@ const Edit = props => { const useEnterRef = useEnter( text, clientId ) const onSplit = useOnSplit( clientId, attributes ) + const onPaste = useOnPaste( clientId, parentBlock?.clientId, attributes, setAttributes ) const onMerge = forward => { mergeBlocks( forward ) @@ -168,6 +170,7 @@ const Edit = props => { className={ textClassNames } onSplit={ onSplit } onMerge={ onMerge } + onPaste={ onPaste } onReplace={ onReplace ? ( blocks, ...args ) => { onReplace( diff --git a/src/block/icon-list-item/util.js b/src/block/icon-list-item/util.js index 1b9d87e6d..ede130acc 100644 --- a/src/block/icon-list-item/util.js +++ b/src/block/icon-list-item/util.js @@ -4,12 +4,15 @@ */ import { useRefEffect } from '@wordpress/compose' import { useCallback, useRef } from '@wordpress/element' -import { useSelect, useDispatch } from '@wordpress/data' +import { + useSelect, useDispatch, dispatch, +} from '@wordpress/data' import { cloneBlock, switchToBlockType, createBlock, getDefaultBlockName, + pasteHandler, } from '@wordpress/blocks' import { store as blockEditorStore } from '@wordpress/block-editor' import { ENTER } from '@wordpress/keycodes' @@ -71,40 +74,6 @@ export const useOnSplit = ( clientId, attributes ) => { }, [ clientId, attributes ] ) } -export const useCopy = clientId => { - const { - getBlockRootClientId, getBlockName, getBlockAttributes, - } = - useSelect( blockEditorStore ) - - return useRefEffect( node => { - function onCopy( event ) { - // The event propagates through all nested lists, so don't override - // when copying nested list items. - if ( event.clipboardData.getData( '__unstableWrapperBlockName' ) ) { - return - } - - const rootClientId = getBlockRootClientId( clientId ) - event.clipboardData.setData( - '__unstableWrapperBlockName', - getBlockName( rootClientId ) - ) - event.clipboardData.setData( - '__unstableWrapperBlockAttributes', - JSON.stringify( getBlockAttributes( rootClientId ) ) - ) - } - - node.addEventListener( 'copy', onCopy ) - node.addEventListener( 'cut', onCopy ) - return () => { - node.removeEventListener( 'copy', onCopy ) - node.removeEventListener( 'cut', onCopy ) - } - }, [] ) -} - export const useEnter = ( text, clientId ) => { const { removeBlocks, selectionChange, insertBlocks, @@ -181,3 +150,44 @@ export const useEnter = ( text, clientId ) => { [ clientId ] ) } + +export const useOnPaste = ( clientId, parentClientId, attributes, setAttributes ) => { + const { insertBlocks } = useDispatch( blockEditorStore ) + const { getBlockIndex } = useSelect( blockEditorStore ) + + return useCallback( event => { + event.preventDefault() + const html = event.clipboardData.getData( 'text/html' ) + const plain = event.clipboardData.getData( 'text/plain' ) + + // Convert first to core/list block. + const list = pasteHandler( { + HTML: html, + plainText: plain, + mode: 'BLOCKS', + } ) + + // If list[0] has inner blocks, it has been converted to core/list block, else list has core/paragraph elements. + const items = list[ 0 ].innerBlocks.length ? list[ 0 ].innerBlocks : list + + const content = items.map( item => item.attributes.content.toPlainText().replaceAll( '\n', '
' ) ) + + // If current icon list item has no text, use the first item as text. + if ( ! attributes.text ) { + const firstItem = content.shift() + setAttributes( { text: firstItem } ) + } + + // create new icon list items + const newBlocks = content.map( text => { + const block = createBlock( 'stackable/icon-list-item', { + ...attributes, + text, + } ) + + return block + } ) + dispatch( 'core/block-editor' ).__unstableMarkNextChangeAsNotPersistent() + insertBlocks( newBlocks, getBlockIndex( clientId ) + 1, parentClientId ) + }, [ clientId, parentClientId, attributes, setAttributes ] ) +}