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

29.08.2026|

Tiempo de lectura Lectura: 6 min, 8 s
Número de palabras Palabras: 1137
Número de visitas Visitas: 135
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.

Actualización 29/08/2026. Se añade una flecha para plegar y desplegar el bloque de código, por defecto aparece plegado y las palabras "Plegar" y "Desplegar" solo aparecen en los post en español, para el resto de idiomas solo muestra la flecha.


 * Añade botones "Copiar", "DEdescargar" y "Desplegar/Plegar" a los bloques de código (PHP + JS + CSS)
 * Inyecta CSS y JS solo si el post actual contiene bloques de código.
 * Muestra texto + icono en español y solo icono en otros idiomas. */
if (!function_exists('botones_codigo_personalizados')) {
    function botones_codigo_personalizados() {
        global $post;
        
        // Optimización: salir si no es un post o no tiene el bloque 'core/code'
        if (!is_a($post, 'WP_Post') || !has_block('core/code', $post)) {
            return;
        }

        // Detección de idioma español (Polylang o nativo de WP)
        $es_espanol = false;
        if (function_exists('pll_current_language')) {
            $es_espanol = (pll_current_language() === 'es');
        } else {
            $es_espanol = (strpos(get_locale(), 'es') === 0);
        }

        // --- INYECCIÓN DE ESTILOS CSS ---
        echo '<style>
        .wp-block-code {
            position: relative;
            padding-top: 40px !important;
            max-height: 120px;
            overflow: hidden;
            transition: max-height 0.25s ease-in-out;
        }
        .wp-block-code.is-expanded {
            max-height: none;
            overflow: visible;
        }
        .custom-code-buttons {
            position: absolute;
            top: 8px;
            right: 12px;
            display: flex;
            align-items: center;
            gap: 6px;
            z-index: 2;
        }
        .custom-code-button {
            background: none;
            border: none;
            padding: 4px;
            cursor: pointer;
            color: #bc080e;
            border-radius: 4px;
            transition: all 0.15s ease;
            width: 28px;
            height: 28px;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .custom-code-button:hover {
            color: #8f060b;
            background: rgba(188, 8, 14, 0.08);
        }
        .custom-code-button svg {
            width: 18px;
            height: 18px;
        }
        .custom-code-toggle {
            background: none;
            border: none;
            padding: 4px 8px;
            cursor: pointer;
            color: #bc080e;
            border-radius: 4px;
            transition: all 0.15s ease;
            font-size: 13px;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 4px;
            line-height: 1;
            height: 28px;
        }
        .custom-code-toggle:hover {
            color: #8f060b;
            background: rgba(188, 8, 14, 0.08);
        }
        .custom-code-toggle svg {
            width: 16px;
            height: 16px;
            transition: transform 0.2s ease;
        }
        .wp-block-code.is-expanded .custom-code-toggle svg,
        .wp-block-code.is-expanded .custom-code-toggle-icon svg {
            transform: rotate(180deg);
        }
        @media (max-width: 480px) {
            .custom-code-buttons {
                top: 6px;
                right: 8px;
            }
        }
        </style>';

        // --- INYECCIÓN DE JAVASCRIPT ---
        echo '<script>
        document.addEventListener("DOMContentLoaded", function() {
            const esEspanol = ' . ($es_espanol ? 'true' : 'false') . ';

            document.querySelectorAll(".wp-block-code").forEach(block => {
                const container = document.createElement("div");
                container.className = "custom-code-buttons";
                
                // Botón Desplegar / Plegar
                const toggleBtn = document.createElement("button");
                toggleBtn.type = "button";
                toggleBtn.setAttribute("notranslate", "true");
                
                if (esEspanol) {
                    toggleBtn.className = "custom-code-toggle";
                    toggleBtn.innerHTML = \'<span>Desplegar</span><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z" fill="currentColor"/></svg>\';
                } else {
                    toggleBtn.className = "custom-code-button custom-code-toggle-icon";
                    toggleBtn.ariaLabel = "Expand / Collapse";
                    toggleBtn.innerHTML = \'<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z" fill="currentColor"/></svg>\';
                }
                
                toggleBtn.addEventListener("click", function() {
                    const isExpanded = block.classList.toggle("is-expanded");
                    if (esEspanol) {
                        const label = toggleBtn.querySelector("span");
                        if (label) {
                            label.textContent = isExpanded ? "Plegar" : "Desplegar";
                        }
                    }
                });

                // Botón Copiar
                const copyBtn = document.createElement("button");
                copyBtn.className = "custom-code-button";
                copyBtn.type = "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="currentColor" 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="currentColor" fill-rule="nonzero"/></svg>\';
                                }, 2000);
                            });
                    }
                });
                
                // Botón Descargar
                const downloadBtn = document.createElement("button");
                downloadBtn.className = "custom-code-button";
                downloadBtn.type = "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" fill="currentColor"/></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" fill="currentColor"/></svg>\';
                        }, 2000);
                    }
                });
                
                container.appendChild(toggleBtn);
                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.

Servicio de optimización de WordPress

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.