NOTE: Apart from
(and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.
Saturday, 28 September 2024
//Less than a minute
En este sitio utilizo Hightlight.js para renderizar fragmentos de código del lado del cliente. Me gusta esto ya que mantiene mi código del lado del servidor limpio y simple. Sin embargo, quería añadir un botón de copia a cada fragmento de código para que los usuarios pudieran copiar fácilmente el código a su portapapeles. Esta es una tarea sencilla, pero pensé que lo documentaría aquí para cualquier otra persona que quisiera hacer lo mismo.
El punto final es que tenemos un botón de copia como este en el sitio:
NOTA: Todo el crédito para este artículo va a Faraz Patankar ¿Quién es el artículo que usé para crear este? Sólo quería documentar los cambios que hice aquí para mi propia referencia y compartir con otros.
Hay un par de maneras de hacer esto; por ejemplo, hay un Complemento del botón de copia para Higlight.js pero decidí que quería más control sobre el botón y el estilo. Así que me encontré este artículo para añadir un botón de copia.
Aunque ese artículo es un gran enfoque, tuvo un par de problemas que dejaron de ser perfecto para mí:
// Lucide copy icon
copyButton.innerHTML = `<svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`;
Mientras que esto funciona, ya uso BoxIcons en este sitio que tiene un copiar icono en allí ya.
// Notify user that the content has been copied
toast.success("Copied to clipboard", {
description: "The code block content has been copied to the clipboard.",
});
Este plugin se engancha en el after:highlightElement
evento y añade un botón al bloque de código.
Así que primero copié el código de Faraz y luego hice los siguientes cambios:
text-xl
.showToast
función que tengo en mi sitio (ver más adelante)aria-label
y title
al botón para la accesibilidad (y para dar un agradable efecto de suspensión).hljs.addPlugin({
"after:highlightElement": ({ el, text }) => {
const wrapper = el.parentElement;
if (wrapper == null) {
return;
}
/**
* Make the parent relative so we can absolutely
* position the copy button
*/
wrapper.classList.add("relative");
const copyButton = document.createElement("button");
copyButton.classList.add(
"absolute",
"top-2",
"right-1",
"p-2",
"text-gray-500",
"hover:text-gray-700",
"bx",
"bx-copy",
"text-xl",
"cursor-pointer"
);
copyButton.setAttribute("aria-label", "Copy code to clipboard");
copyButton.setAttribute("title", "Copy code to clipboard");
copyButton.onclick = () => {
navigator.clipboard.writeText(text);
// Notify user that the content has been copied
showToast("The code block content has been copied to the clipboard.", 3000, "success");
};
// Append the copy button to the wrapper
wrapper.prepend(copyButton);
},
});
showToast
FunciónEsto depende de una navaja parcial que añadí a mi proyecto. Este parcial utiliza la DaisyUI Componente de tostada para mostrar un mensaje al usuario. Me gusta este enfoque ya que mantiene el Javascript limpio y sencillo y me permite peinar el mensaje de brindis de la misma manera que el resto del sitio.
<div id="toast" class="toast toast-bottom fixed z-50 hidden overflow-y-hidden">
<div id="toast-message" class="alert">
<div>
<span id="toast-text">Notification message</span>
</div>
</div>
<p class="hidden right-1 bx-copy cursor-pointer alert-success alert-warning alert-error alert-info"></p>
</div>
Usted notará que esto también tiene un extraño oculto p
etiqueta en la parte inferior, esto es sólo para Tailwind para analizar estas clases cuando se construye CSS del sitio.
La función Javascript es simple, sólo muestra el mensaje de brindis para un tiempo establecido y luego lo oculta de nuevo.
window.showToast = function(message, duration = 3000, type = 'success') {
const toast = document.getElementById('toast');
const toastText = document.getElementById('toast-text');
const toastMessage = document.getElementById('toast-message');
// Set message and type
toastText.innerText = message;
toastMessage.className = `alert alert-${type}`; // Change alert type (success, warning, error)
// Show the toast
toast.classList.remove('hidden');
// Hide the toast after specified duration
setTimeout(() => {
toast.classList.add('hidden');
}, duration);
}
Entonces podemos llamar a esto usando el showToast
función en la copyButton.onclick
evento.
showToast("The code block content has been copied to the clipboard.", 3000, "success");
He añadido esta derecha parcial en la parte superior de mi _Layout.cshtml
archivo por lo que está disponible en cada página.
<partial name="_Toast" />``
Ahora, cuando mostramos los posts del blog los bloques de código tienen:
Así que eso es todo, un simple cambio en el código de Faraz para que funcione para mí. Espero que esto ayude a alguien más.