
저는 이에 대해 여러 번 생각하고 글을 썼습니다. 왜 워드프레스가 구텐베르크 블록에 특정 기본 기능을 추가하지 않는지, 목차 블록의 경우처럼 코어에 통합하는 최종 버전까지 왜 한 세기가 걸리는지 잘 이해가 가지 않습니다.
이번에는 구텐베르크 코드 블록이 없는 매우 유용하고 제가 항상 놓쳤던, 그리고 필수라고 생각하는 기능을 추가하려고 합니다. 복사 및 다운로드 버튼입니다.
사용된 복사 버튼은 아이콘몬스터의 이 버튼이며, 도구 설명과 녹색으로 복사를 시각적으로 확인할 수 있습니다.
아이콘몬스트르의 다운로드 버튼은 모든 것을 .txt 형식으로 다운로드하지만, 제 용도로는 이 정도면 충분합니다.
두 버튼 모두 부드러운 호버링이 있어 미니멀한 스타일을 유지합니다.
성능 측면에서는 코드 블록이 있고 CSS와 JS가 최적화되어 인라인으로 표시되는 페이지에서만 로드됩니다.
템플릿 또는 하위 테마의 functions.php 파일에 추가하기만 하면 필요한 코드가 블록 자체에서 바로 작동하는 것을 확인할 수 있습니다.
/**
* 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');