@wordpress/blocks
Version:
Block API for WordPress.
75 lines (66 loc) • 2.27 kB
text/typescript
/**
* WordPress dependencies
*/
import { Platform } from '@wordpress/element';
/**
* Internal dependencies
*/
import { createBlock, findTransform } from '../factory';
import parse from '../parser';
import { getBlockAttributes } from '../parser/get-block-attributes';
import { getRawTransforms } from './get-raw-transforms';
import type { Block } from '../../types';
/**
* Converts HTML directly to blocks. Looks for a matching transform for each
* top-level tag. The HTML should be filtered to not have any text between
* top-level tags and formatted in a way that blocks can handle the HTML.
*
* @param html HTML to convert.
* @param handler The handler calling htmlToBlocks: either rawHandler
* or pasteHandler.
*
* @return An array of blocks.
*/
export function htmlToBlocks(
html: string,
handler: ( options: { HTML: string } ) => Block[] | string
): Block[] {
const doc = document.implementation.createHTMLDocument( '' );
doc.body.innerHTML = html;
return Array.from( doc.body.children ).flatMap( ( node ) => {
const transforms = getRawTransforms();
const rawTransform = findTransform(
transforms as unknown as Parameters< typeof findTransform >[ 0 ],
( ( t: unknown ) => {
const transform = t as ( typeof transforms )[ number ];
return transform.isMatch( node );
} ) as Parameters< typeof findTransform >[ 1 ]
) as unknown as ( typeof transforms )[ number ] | null;
if ( ! rawTransform ) {
// Until the HTML block is supported in the native version, we'll parse it
// instead of creating the block to generate it as an unsupported block.
if ( ( Platform as Record< string, unknown > ).isNative ) {
return parse(
`<!-- wp:html -->${ node.outerHTML }<!-- /wp:html -->`
);
}
return createBlock(
// Should not be hardcoded.
'core/html',
getBlockAttributes( 'core/html', node.outerHTML )
);
}
const { transform, blockName } = rawTransform;
if ( transform ) {
const block = transform( node, handler ) as Block;
if ( node.hasAttribute( 'class' ) ) {
block.attributes.className = node.getAttribute( 'class' );
}
return block;
}
return createBlock(
blockName!,
getBlockAttributes( blockName!, node.outerHTML )
);
} );
}