From 0bd0a5daee782e71c75d04c423b068c354129b22 Mon Sep 17 00:00:00 2001 From: mxkae Date: Tue, 2 Jul 2024 13:09:19 +0800 Subject: [PATCH 1/4] remove unused useCopy --- src/block/icon-list-item/util.js | 34 -------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/block/icon-list-item/util.js b/src/block/icon-list-item/util.js index 1b9d87e6d..2b03e3a15 100644 --- a/src/block/icon-list-item/util.js +++ b/src/block/icon-list-item/util.js @@ -71,40 +71,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, From d5d170cc98e3b62eada72b593db56a5474f36528 Mon Sep 17 00:00:00 2001 From: mxkae Date: Tue, 2 Jul 2024 13:10:31 +0800 Subject: [PATCH 2/4] add onPaste --- src/block/icon-list-item/edit.js | 3 +++ src/block/icon-list-item/util.js | 36 +++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) 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 2b03e3a15..4a02d2cad 100644 --- a/src/block/icon-list-item/util.js +++ b/src/block/icon-list-item/util.js @@ -4,7 +4,9 @@ */ 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, @@ -147,3 +149,35 @@ export const useEnter = ( text, clientId ) => { [ clientId ] ) } + +export const useOnPaste = ( clientId, parentClientId, attributes, setAttributes ) => { + const { insertBlocks } = useDispatch( blockEditorStore ) + const { getBlockIndex } = useSelect( blockEditorStore ) + + const parser = new DOMParser() + + return useCallback( event => { + event.preventDefault() + const content = event.clipboardData.getData( 'text/html' ) + const dom = parser.parseFromString( content, 'text/html' ) + + const listItems = dom.querySelectorAll( 'li' ) + const listItemsContent = Array.from( listItems ).map( item => item.innerHTML ) + + if ( ! attributes.text ) { + const firstItem = listItemsContent.shift() + setAttributes( { text: firstItem } ) + } + + const newBlocks = listItemsContent.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 ] ) +} From 9322fa7b60b58e1bdef17d37bb9667334dd0379f Mon Sep 17 00:00:00 2001 From: mxkae Date: Mon, 8 Jul 2024 23:05:38 +0800 Subject: [PATCH 3/4] fix on paste for lists from ms word and gdocs --- src/block/icon-list-item/util.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/block/icon-list-item/util.js b/src/block/icon-list-item/util.js index 4a02d2cad..ba3d9e19f 100644 --- a/src/block/icon-list-item/util.js +++ b/src/block/icon-list-item/util.js @@ -12,6 +12,7 @@ import { switchToBlockType, createBlock, getDefaultBlockName, + pasteHandler, } from '@wordpress/blocks' import { store as blockEditorStore } from '@wordpress/block-editor' import { ENTER } from '@wordpress/keycodes' @@ -154,22 +155,30 @@ export const useOnPaste = ( clientId, parentClientId, attributes, setAttributes const { insertBlocks } = useDispatch( blockEditorStore ) const { getBlockIndex } = useSelect( blockEditorStore ) - const parser = new DOMParser() - return useCallback( event => { event.preventDefault() - const content = event.clipboardData.getData( 'text/html' ) - const dom = parser.parseFromString( content, 'text/html' ) + 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', + } ) + + const items = list[ 0 ].innerBlocks - const listItems = dom.querySelectorAll( 'li' ) - const listItemsContent = Array.from( listItems ).map( item => item.innerHTML ) + 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 = listItemsContent.shift() + const firstItem = content.shift() setAttributes( { text: firstItem } ) } - const newBlocks = listItemsContent.map( text => { + // create new icon list items + const newBlocks = content.map( text => { const block = createBlock( 'stackable/icon-list-item', { ...attributes, text, From 71fe17c7231ed8cadb8ea0f466d484f7b20b6833 Mon Sep 17 00:00:00 2001 From: mxkae Date: Fri, 12 Jul 2024 08:21:14 +0800 Subject: [PATCH 4/4] update onPaste --- src/block/icon-list-item/util.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/block/icon-list-item/util.js b/src/block/icon-list-item/util.js index ba3d9e19f..ede130acc 100644 --- a/src/block/icon-list-item/util.js +++ b/src/block/icon-list-item/util.js @@ -167,7 +167,8 @@ export const useOnPaste = ( clientId, parentClientId, attributes, setAttributes mode: 'BLOCKS', } ) - const items = list[ 0 ].innerBlocks + // 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', '
' ) )