Back to "Un pulsante Copia per Highlight.js"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

DaisyUI Highlight.js Javascript Tailwind

Un pulsante Copia per Highlight.js

Saturday, 28 September 2024

Introduzione

In questo sito uso Highlight.js per rendere client snippet di codice lato. Mi piace questo come mantiene il mio codice laterale server pulito e semplice. Tuttavia, volevo aggiungere un pulsante di copia ad ogni frammento di codice in modo che gli utenti potessero facilmente copiare il codice negli appunti. Questo è un compito semplice, ma ho pensato di documentarlo qui per chiunque altro voglia fare lo stesso.

Oh e questo è tutto in attesa di me aggiungendo la funzionalità della newsletter per effettivamente presentarsi sul sito. Non appena avro' l'energia per farlo, lo aggiungero'.

L'endpoint è che abbiamo un pulsante di copia come questo sul sito: Pulsante copia

NOTA: Tutto il credito per questo articolo va a Faraz PatankarCity name (optional, probably does not need a translation) Chi è l'articolo che ho usato per creare questo. Volevo solo documentare i cambiamenti che ho fatto qui per il mio riferimento e per condividere con gli altri.

Le opzioni

Ci sono un paio di modi per farlo; per esempio c'è un plugin pulsante copia per Higlight.js ma ho deciso che volevo più controllo sul pulsante e lo styling. Cosi' mi sono imbattuto... questo articolo per aggiungere un pulsante copia.

I problemi

Mentre quell'articolo è un grande approccio aveva un paio di problemi che ha smesso di essere perfetto per me:

  1. Usa un carattere che non uso sul mio sito (ma poi manualmente ha il SVG troppo, non so perché).
  // 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>`;

Mentre questo funziona, Io già uso BoxIcons su questo sito che ha un copia l'icona già dentro.

  1. Usa una biblioteca di brindisi che non ho su questo sito.
  // Notify user that the content has been copied
      toast.success("Copied to clipboard", {
        description: "The code block content has been copied to the clipboard.",
      });
  1. Abbatte il flusso di y sul blocco di codice e mette l'icona in basso che non volevo. Quindi il mio e' in alto a destra.

I miei adattamenti

La funzione principale

Questo gancio del plugin nel after:highlightElement evento e aggiunge un pulsante al blocco di codice.

Quindi prima ho copiato il codice di Faraz e poi ho fatto le seguenti modifiche:

  1. Invece di aggiungerla alla fine del blocco di codice, l'ho preparata all'inizio.
  2. Invece del SVG ho usato la versione BoxIcons semplicemente aggiungendo queste classi al pulsante inserito e impostando il testo a text-xl.
  3. Ho rimosso la notifica di brindisi e l'ho sostituita con una semplice showToast funzione che ho nel mio sito (vedi più avanti)
  4. Ho aggiunto un aria-label e title al pulsante per l'accessibilità (e per dare un bel effetto di hover).
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 Funzione

Questo si basa su un rasoio parziale ho aggiunto al mio progetto. Questo parziale utilizza il Componente toast DaisyUI per mostrare un messaggio all'utente. Mi piace questo approccio in quanto mantiene il Javascript pulito e semplice e mi permette di stilare il messaggio toast allo stesso modo del resto del sito.

<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>

Noterete che anche questo ha uno strano nascondiglio p tag in basso, questo è solo per Tailwind per analizzare queste classi quando si costruisce CSS del sito.

La funzione Javascript è semplice, mostra solo il messaggio toast per un tempo impostato e poi lo nasconde di nuovo.

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);
}

Possiamo poi chiamare questo usando il showToast funzione nella copyButton.onclick evento.

showToast("The code block content has been copied to the clipboard.", 3000, "success");

Ho aggiunto questo diritto parziale in cima alla mia _Layout.cshtml file in modo che sia disponibile su ogni pagina.

<partial name="_Toast"  />``

Ora quando mostriamo i post del blog i blocchi di codice hanno: Pulsante copia

In conclusione

Quindi questo è tutto, un semplice cambiamento al codice di Faraz per farlo funzionare per me. Spero che questo aiuti qualcun altro la' fuori.

logo

©2024 Scott Galloway