Custom Block Transformers
WP Block to HTML provides a flexible API for creating custom block transformers to handle special cases or extend support for custom blocks.
Introduction to Block Transformers
Block transformers are functions that convert WordPress block data into HTML. The library includes default transformers for all WordPress core blocks, but you can create custom transformers for:
- Custom Blocks: Handle blocks from plugins or custom WordPress implementations
- Special Styling: Apply custom styling or structure to specific blocks
- Extended Functionality: Add additional features like analytics tracking or special attributes
Creating a Custom Block Transformer
The createBlockHandler
function makes it easy to create custom block transformers:
import { createBlockHandler, convertBlocks } from 'wp-block-to-html';
const customParagraphHandler = createBlockHandler('core/paragraph', {
transform(block, options) {
const { attrs = {}, innerContent = [] } = block;
const { align = '', fontSize = '', dropCap = false } = attrs;
// Extract text content from the paragraph
const content = innerContent[0].replace(/<\/?p[^>]*>/g, '');
// Apply custom styling based on attributes
let className = '';
if (align) {
className += options.cssFramework === 'tailwind'
? `text-${align} `
: `has-text-align-${align} `;
}
if (fontSize) {
className += options.cssFramework === 'tailwind'
? `text-${fontSize} `
: `has-${fontSize}-font-size `;
}
if (dropCap) {
className += options.cssFramework === 'tailwind'
? 'first-letter:text-5xl first-letter:font-bold first-letter:float-left first-letter:mr-2 '
: 'has-drop-cap ';
}
return `<p class="${className.trim()}">${content}</p>`;
}
});
// Use the custom transformer
const html = convertBlocks(blockData, {
blockTransformers: {
'core/paragraph': customParagraphHandler
}
});
Block Transformer Interface
A block transformer must implement the transform
method:
interface BlockTransformer {
transform(block: WordPressBlock, options: ConversionOptions): string;
}
block
: The WordPress block object to transformoptions
: The configuration options for the conversion- Returns: HTML string representing the transformed block
Overriding Default Transformers
You can override the default transformers for core blocks by providing your own in the blockTransformers
option:
import { convertBlocks } from 'wp-block-to-html';
const html = convertBlocks(blockData, {
blockTransformers: {
'core/heading': {
transform(block, options) {
const { attrs = {} } = block;
const { level = 2, content = '', align = '' } = attrs;
// Custom implementation for headings
return `<h${level} class="custom-heading ${align ? `align-${align}` : ''}">${content}</h${level}>`;
}
}
}
});
Handling Custom WordPress Blocks
For blocks from plugins or custom implementations:
import { createBlockHandler, convertBlocks } from 'wp-block-to-html';
// Handler for a custom testimonial block
const testimonialBlockHandler = createBlockHandler('acme/testimonial', {
transform(block, options) {
const { attrs = {}, innerBlocks = [] } = block;
const { author = '', role = '', rating = 5 } = attrs;
// Process the content from inner blocks
let testimonialContent = '';
if (innerBlocks.length > 0) {
testimonialContent = innerBlocks.map(innerBlock =>
convertBlocks(innerBlock, options)
).join('');
}
// Generate stars for rating
const stars = '★'.repeat(rating) + '☆'.repeat(5 - rating);
// Return custom HTML structure
return `
<div class="testimonial">
<div class="testimonial-content">${testimonialContent}</div>
<div class="testimonial-meta">
<div class="testimonial-author">${author}</div>
<div class="testimonial-role">${role}</div>
<div class="testimonial-rating">${stars}</div>
</div>
</div>
`;
}
});
// Use the custom block handler
const html = convertBlocks(blockData, {
blockTransformers: {
'acme/testimonial': testimonialBlockHandler
}
});
Accessing CSS Framework Options
Block transformers have access to the current CSS framework and custom class mappings:
createBlockHandler('core/button', {
transform(block, options) {
const { attrs = {}, innerContent = [] } = block;
const { url = '#', text = '', style = {} } = attrs;
// Get appropriate button classes based on CSS framework
let className = '';
if (options.cssFramework === 'tailwind') {
className = 'px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600';
} else if (options.cssFramework === 'bootstrap') {
className = 'btn btn-primary';
} else {
className = 'wp-block-button__link';
}
// Apply custom style
const styleAttr = style.color
? `style="background-color:${style.color.background};color:${style.color.text}"`
: '';
return `<a href="${url}" class="${className}" ${styleAttr}>${text}</a>`;
}
});
Common Use Cases
Adding Data Attributes
createBlockHandler('core/image', {
transform(block, options) {
const { attrs = {} } = block;
const { url, alt = '', id, width, height } = attrs;
// Add data attributes for lazy loading, lightbox, etc.
return `
<img
src="${url}"
alt="${alt}"
width="${width}"
height="${height}"
data-id="${id}"
data-lightbox="gallery"
data-caption="${alt}"
/>
`;
}
});
Adding Analytics Tracking
createBlockHandler('core/button', {
transform(block, options) {
const { attrs = {} } = block;
const { url = '#', text = '' } = attrs;
// Add analytics tracking attributes
return `
<a
href="${url}"
class="button"
data-tracking="true"
data-event-category="Button"
data-event-action="Click"
data-event-label="${text}"
>
${text}
</a>
`;
}
});
Supporting Third-Party Blocks
// Support for a WooCommerce product block
createBlockHandler('woocommerce/product', {
transform(block, options) {
const { attrs = {} } = block;
const { id, showPrice = true, showTitle = true, showImage = true } = attrs;
// In a real implementation, you might fetch product data
// or use data already available in the block
return `
<div class="product" data-product-id="${id}">
${showImage ? '<div class="product-image"><!-- Image HTML --></div>' : ''}
${showTitle ? '<h3 class="product-title">Product Title</h3>' : ''}
${showPrice ? '<div class="product-price">$99.99</div>' : ''}
<button class="add-to-cart">Add to Cart</button>
</div>
`;
}
});
Best Practices
When creating custom block transformers:
- Respect Content Handling Mode: Check
options.contentHandling
to decide how to process content - Framework Compatibility: Adapt your output based on
options.cssFramework
- Handle Nested Blocks: Use
convertBlocks
recursively for inner blocks - Sanitize Content: Ensure your output HTML is properly sanitized
- Preserve Accessibility: Maintain important accessibility attributes
- Consider SSR: If using server-side rendering, maintain compatibility with optimizations