Añadir botones de copiar y descargar en los bloques de código de Gutenberg sin plugins

08.08.2025|

Tiempo de lectura Lectura: 4 min, 23 s
Número de palabras Palabras: 812
Número de visitas Visitas: 125
Icono de traducción
Añadir botones de copiar y descargar en los bloques de código de Gutenberg sin plugins

Lo he pensado y escrito más de una vez. No termino de entender porqué WordPress no añade determinadas funciones básicas en sus bloques de Gutenberg o tarda un siglo en llevarlas a sus versiones finales que incorpora al core, como es el caso del bloque de tablas de contenido.

En esta ocasión vamos a añadir algo muy útil y que siempre he echado de menos, que no tiene el bloque de código de Gutenberg y que considero imprescindible. Botones de copiar y descargar.

El botón de copiar usado es este deIconmonstr, tiene tooltip y confirmación visual de copiado en color verde.

El botón de descargar, también de Iconmonstr, descarga todo en formato .txt, pero para el uso que le doy, para mí es suficiente.

Ambos botones tienen un hover suave para mantener un estilo minimalista.

En cuanto al rendimiento, solo se carga en aquellas páginas donde hay bloques de código presentes y el CSS y el JS están optimizados e inline.

Puedes verlo funcionando aquí mismo en el propio bloque con el código necesario que basta añadir al archivo functions.php de tu plantilla o tema hijo.

/**
 * Añade botones "Copiar" y "Descargar" en los bloques de código <code> de Gutenberg
 */
function botones_codigo_personalizados() {
    global $post;
    if (!is_a($post, 'WP_Post') || !has_block('core/code', $post)) {
        return;
    }

    echo '<style>
    .wp-block-code {
        position: relative;
        padding-top: 12px !important;
    }
    .custom-code-buttons {
        position: absolute;
        top: 12px;
        right: 12px;
        display: flex;
        gap: 8px;
    }
    .custom-code-button {
        background: none;
        border: none;
        padding: 4px;
        cursor: pointer;
        color: #6b7280;
        border-radius: 4px;
        transition: all 0.15s ease;
        width: 24px;
        height: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .custom-code-button:hover {
        color: #374151;
        background: rgba(0,0,0,0.05);
    }
    .custom-code-button svg {
        width: 16px;
        height: 16px;
    }
    @media (max-width: 480px) {
        .custom-code-buttons {
            top: 8px;
            right: 8px;
        }
    }
    </style>';

    echo '<script>
    document.addEventListener("DOMContentLoaded", function() {
        document.querySelectorAll(".wp-block-code").forEach(block => {
            const container = document.createElement("div");
            container.className = "custom-code-buttons";
            
            // Botón Copiar, icono de Iconmonstr
            const copyBtn = document.createElement("button");
            copyBtn.className = "custom-code-button";
            copyBtn.title = "Copiar código";
            copyBtn.innerHTML = \'<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m6 18h-3c-.48 0-1-.379-1-1v-14c0-.481.38-1 1-1h14c.621 0 1 .522 1 1v3h3c.621 0 1 .522 1 1v14c0 .621-.522 1-1 1h-14c-.48 0-1-.379-1-1zm1.5-10.5v13h13v-13zm9-1.5v-2.5h-13v13h2.5v-9.5c0-.481.38-1 1-1z" fill-rule="nonzero"/></svg>\';
            
            copyBtn.addEventListener("click", function() {
                const code = block.querySelector("code");
                if (code) {
                    navigator.clipboard.writeText(code.textContent)
                        .then(() => {
                            copyBtn.innerHTML = \'<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m6 18h-3c-.48 0-1-.379-1-1v-14c0-.481.38-1 1-1h14c.621 0 1 .522 1 1v3h3c.621 0 1 .522 1 1v14c0 .621-.522 1-1 1h-14c-.48 0-1-.379-1-1zm1.5-10.5v13h13v-13zm9-1.5v-2.5h-13v13h2.5v-9.5c0-.481.38-1 1-1z" fill="#10b981" fill-rule="nonzero"/></svg>\';
                            setTimeout(() => {
                                copyBtn.innerHTML = \'<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m6 18h-3c-.48 0-1-.379-1-1v-14c0-.481.38-1 1-1h14c.621 0 1 .522 1 1v3h3c.621 0 1 .522 1 1v14c0 .621-.522 1-1 1h-14c-.48 0-1-.379-1-1zm1.5-10.5v13h13v-13zm9-1.5v-2.5h-13v13h2.5v-9.5c0-.481.38-1 1-1z" fill-rule="nonzero"/></svg>\';
                            }, 2000);
                        });
                }
            });
            
            // Botón Descargar, icono de Iconmonstr
            const downloadBtn = document.createElement("button");
            downloadBtn.className = "custom-code-button";
            downloadBtn.title = "Descargar código";
            downloadBtn.innerHTML = \'<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 21l-8-9h6v-12h4v12h6l-8 9zm9-1v2h-18v-2h-2v4h22v-4h-2z"/></svg>\';
            
            downloadBtn.addEventListener("click", function() {
                const code = block.querySelector("code");
                if (code) {
                    const blob = new Blob([code.textContent], { type: "text/plain" });
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement("a");
                    a.href = url;
                    a.download = "codigo.txt";
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);
                    
                    downloadBtn.innerHTML = \'<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 21l-8-9h6v-12h4v12h6l-8 9zm9-1v2h-18v-2h-2v4h22v-4h-2z" fill="#10b981"/></svg>\';
                    setTimeout(() => {
                        downloadBtn.innerHTML = \'<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 21l-8-9h6v-12h4v12h6l-8 9zm9-1v2h-18v-2h-2v4h22v-4h-2z"/></svg>\';
                    }, 2000);
                }
            });
            
            container.appendChild(copyBtn);
            container.appendChild(downloadBtn);
            block.appendChild(container);
        });
    });
    </script>';
}
add_action('wp_footer', 'botones_codigo_personalizados');

Y si quieren solo un botón con el texto "Copiar código", sin imagen, por aquí pueden encontrar el código.

Donar

Documentales sobre dibujantesTontolares, los titulares más tontos

Este blog se aloja en LucusHost

LucusHost, el mejor hosting

Tu WordPress puede volar

Servicio de optimización de WordPress
Quiero velocidad

Servicio de optimización

Suscripción por e-mail

Recibe gratis los artículos completos en tu correo sin publicidad en el momento que se publiquen. Se envía el contenido íntegro del feed sin herramientas externas y sin anuncios.