/
githubmirror
/
gutenberg
Обзор
Документация
Войти
/
githubmirror
/
gutenberg
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
trunk
packages/block-library/src/html/edit.js
162 строки
5 KB
Marco Ciampini
ESLint: Replace strict config with bulk suppressions (#81248)
07 авг 2026, 14:34
Не верифицирован
07 авг 2026, 14:34
7f43eaf
Код
Авторство
О чём код?
import { __ } from '@wordpress/i18n'; import { useEffect, useState } from '@wordpress/element'; import { BlockControls, BlockIcon, InspectorControls, useBlockProps, store as blockEditorStore, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; import { parse, serialize, getBlockContent } from '@wordpress/blocks'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import deprecated from '@wordpress/deprecated'; import { ToolbarButton, ToolbarGroup, Placeholder, Button, __experimentalVStack as VStack, } from '@wordpress/components'; import { code } from '@wordpress/icons'; import { unlock } from '../lock-unlock'; import HTMLEditModal from './modal'; const { InnerContent } = unlock( blockEditorPrivateApis ); export default function HTMLEdit( { clientId, attributes } ) { const [ isModalOpen, setIsModalOpen ] = useState( false ); const registry = useRegistry(); const { updateBlock, replaceInnerBlocks } = useDispatch( blockEditorStore ); const content = useSelect( ( select ) => { const block = select( blockEditorStore ).getBlock( clientId ); return block ? getBlockContent( block ) : ''; }, [ clientId ] ); const blockProps = useBlockProps( { className: 'block-library-html__edit', } ); // Re-parse the edited content: static HTML becomes the block's // `innerContent` fragments and `<!-- wp:* -->` delimited segments become // inner blocks mounted at their positions within the static markup. const onUpdate = ( nextContent ) => { if ( nextContent === content ) { return; } const [ parsedBlock ] = parse( `<!-- wp:html -->\n${ nextContent }\n<!-- /wp:html -->` ); const nextInnerBlocks = parsedBlock?.innerBlocks ?? []; const prevInnerBlocks = registry .select( blockEditorStore ) .getBlocks( clientId ); // Keep the existing inner blocks, and thereby their client IDs and // selection, when their markup is unchanged — e.g. when only the // surrounding static HTML was edited. const innerBlocksUnchanged = prevInnerBlocks.length === nextInnerBlocks.length && prevInnerBlocks.every( ( block, index ) => serialize( block ) === serialize( nextInnerBlocks[ index ] ) ); registry.batch( () => { updateBlock( clientId, { innerContent: parsedBlock?.innerContent ?? ( nextContent ? [ nextContent ] : [] ), } ); if ( ! innerBlocksUnchanged ) { replaceInnerBlocks( clientId, nextInnerBlocks, false ); } } ); }; // Migrate the deprecated `content` attribute. The block's markup now lives // in its inner content, but a block created via `createBlock( 'core/html', // { content } )` still arrives with a `content` attribute. As soon as it // loads, move that markup into the block's inner content and clear the // attribute. useEffect( () => { if ( ! attributes.content ) { return; } deprecated( 'The content attribute on the Custom HTML block', { since: '7.1', alternative: 'inner content', } ); updateBlock( clientId, { attributes: { content: undefined }, innerContent: [ attributes.content ], } ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [ attributes.content ] ); // Show placeholder when content is empty if ( ! content?.trim() ) { return ( <div { ...blockProps }> <Placeholder icon={ <BlockIcon icon={ code } /> } label={ __( 'Custom HTML' ) } instructions={ __( 'Add custom HTML code and preview how it looks.' ) } > <Button __next40pxDefaultSize variant="primary" onClick={ () => setIsModalOpen( true ) } > { __( 'Edit HTML' ) } </Button> </Placeholder> { isModalOpen && ( <HTMLEditModal onRequestClose={ () => setIsModalOpen( false ) } content={ content } onUpdate={ onUpdate } /> ) } </div> ); } return ( <div { ...blockProps }> <BlockControls> <ToolbarGroup> <ToolbarButton onClick={ () => setIsModalOpen( true ) }> { __( 'Edit code' ) } </ToolbarButton> </ToolbarGroup> </BlockControls> <InspectorControls> <VStack className="block-library-html__edit-code" expanded> <Button className="block-library-html__edit-code-button" __next40pxDefaultSize variant="secondary" onClick={ () => setIsModalOpen( true ) } > { __( 'Edit code' ) } </Button> </VStack> </InspectorControls> <InnerContent clientId={ clientId } /> { isModalOpen && ( <HTMLEditModal onRequestClose={ () => setIsModalOpen( false ) } content={ content } onUpdate={ onUpdate } /> ) } </div> ); }