logo

Cómo preparar bloques Gutenberg para utilizarlos en un entorno Headless con React

08 julio 2023

Este post es el segundo de una serie de artículos que tiene com objetivo utilizar una librería de resaltado de código (como react-syntax-highlighter) en el front end que necesitará de datos personalizados para saber cómo mostrar el código añadido.

Índice de Contenidos

Introducción

En este artículo explicaré como podemos preparar nuestro bloque Gutenberg para poder utilizarlo en una web con React, tal como sería en una arquitectura Headless.

En un principio los bloques Gutenberg creados de manera estática, es decir que su contenido se guarda en la base de datos como puro HTML, no necesariamente necesitan de ningún tratamiento especial a la hora de renderizarlos en una aplicación con React ya que simplemente el output es HTML y se pueden renderizar tal cual.

Pero habrán casos en los que queramos sustituir un bloque por un componente en React, por ejemplo un bloque que necesite de cierta interactividad por parte del usuario, como podría ser un Accordion o un bloque de resaltado de código, sin interactividad pero precisa de una librería externa para ser formateado, como el ejemplo de este artículo.

En este ejemplo voy a utilizar el bloque de Código de WordPress, el cual prepararemos para poder sustituirlo por un componente de resaltado de código utilizando la librería react-syntax-highlighter

Partiré del artículo Cómo personalizar los bloques existentes de Gutenberg con campos adicionales donde expliqué como añadir campos adicionales al bloque de Código existente en WordPress core y desde aquí veremos cómo exponer los atributos para ser utilizados como props en nuestro componente React.

Preparar los atributos del bloque Gutenberg para React

Si trabajamos sobre nuestros propios bloques que hemos creado, es fácil añadir los atributos del bloque al markup HTML del bloque, podríamos simplemente añadirlo como un atributo data a un div, que nos serviría de «placeholder» (o marcador de posición), en formato json y en React podríamos extraer esos atributos del elemento (veremos cómo hacerlo en el próximo post).

El markup de nuestro bloque sería algo así:

<div data-wp-block="<?php echo esc_attr( wp_json_encode( $args ) ); ?>"></div>

Pero en el ejemplo de bloque de Código de WordPress tendremos que modificar los atributos mediante el hook render_block, que nos permite modificar el contenido de un bloque en particular.

Este método también servirá para nuestros propios bloques así que nos centraremos en este enfoque con más detalle.

Con la ayuda de WP_HTML_Tag_Processor, introducido en WordPress 6.2, el proceso de añadir atributos al html del bloque es más sencillo.

Básicamente tendremos que crear una nueva instancia de WP_HTML_Tag_Processor pasando el html que queramos modificar (el html del bloque) y añadiendo el atributo que deseamos a través de los métodos que nos ofrece dicha clase.

El uso de WP_HTML_Tag_Processor sustituye al clásico
$doc = new DomDocument( ‘1.0’, ‘UTF-8’ );

$doc->saveHTML();

El código quedaría de tal manera:

add_filter( 'render_block', 'render_code_block', 10, 3 );

/**
 * Filter code render block
 *
 * @param string    $block_content  The block content
 * @param array     $block          The full block, including name and attributes
 * @param \WP_Block $instance       The block instance
 *
 * @return string
 */
function render_code_block( $block_content, $block, $instance ): string {

     // Comprobar que el bloque es el que queremos modificar.
     if ( ! $block_content || $block['blockName'] !== 'core/code' ) {
        return $block_content;
     }
     
     // Crear una instancia de WP_HTML_Tag_Processor con el html del bloque.
     $processor = new WP_HTML_Tag_Processor( $block_content );

     // Declarar atributos por defecto y sobrescribir atributos.
     $default_attrs = [
	  'language' => 'javascript',
	  'showLineNumbers' => true,
	  'startingLineNumber' => 1,
     ];
    
    $block_attrs = wp_parse_args( $instance->attributes, $default_attrs );

    // Serializar valores de atributos y añadir atributos data.
    $attrs_serialized = wp_json_encode( $block_attrs );

    if ( $processor->next_tag() ) {
	  $processor->set_attribute( 'data-wp-block-name', esc_attr( $block['blockName'] ) );
	  $processor->set_attribute( 'data-wp-block', $attrs_serialized );

        return $processor->get_updated_html();
    }
		
     return $block_content;
}

El código aquí es muy específico a nuestro bloque de código y a los atributos personalizados que hemos añadido, si quieres un ejemplo de algo más genérico para todos los bloques te recomiendo que explores el código en Headstartwp

*Nota al margen: Headstartwp es un open source NextJS framework diseñado exclusivamente para Headless WordPress desarrollado por 10up.

Para comprobar que todo esto ha funcionado, crea un post en WP con un bloque de código, pega algo de código, guarda los atributos que asignes, y en el navegador dirígete a https://mi-sitio.es/wp-json/wp/v2/posts/[ID del post], y podrás comprobar en el content los atributos data-wp-block-name y data-wp-block se han añadido.

En este otro artículo explico como usaremos estos nuevos atributos desde nuestro Front End en React para sustituir nuestro bloque de código con un componente react y la ayuda de react-syntax-highlighter