Back to "En kopieringsknapp för 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

Javascript Tailwind DaisyUI Highlight.js

En kopieringsknapp för highlight.js

Saturday, 28 September 2024

Inledning

På denna webbplats använder jag Hightlight.js för att rendera kod sippets klient sida. Jag gillar det här eftersom det håller min server sidokod ren och enkel. Men jag ville lägga till en kopia knapp till varje kod sippet så att användarna enkelt kunde kopiera koden till deras klippbordet. Detta är en enkel uppgift, men jag tänkte att jag skulle dokumentera den här för alla andra som kanske vill göra samma sak.

Åh och detta är allt väntar på mig lägga till nyhetsbrev funktionalitet för att faktiskt dyka upp på webbplatsen. Så fort jag får energi att göra det ska jag lägga till det här.

Slutmålet är att vi har en kopia knapp som denna på webbplatsen: Kopiera knapp

OBS: All kredit för denna artikel går till Faraz Patankar Ordförande Vems artikel jag brukade skapa den här. Jag ville bara dokumentera de ändringar jag gjorde här för min egen skull och för att dela med mig av dem till andra.

Alternativen

Det finns ett par sätt att göra detta; till exempel finns det en Insticksprogram för kopieringsknappName för Higlight.js men jag bestämde mig för att jag ville ha mer kontroll över knappen och stylingen. Så jag stötte på dig. den här artikeln för att lägga till en kopieringsknapp.

Problemen

Även om den artikeln är ett bra tillvägagångssätt hade den ett par frågor som slutade vara perfekt för mig:

  1. Den använder ett teckensnitt som jag inte använder på min webbplats (men sedan manuellt har SVG också, inte säker på varför).
  // 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>`;

Medan detta fungerar, Jag använder redan BoxIcons på denna webbplats som har en kopiera ikonen redan där.

  1. Den använder ett rostat bibliotek som jag inte har på den här sidan.
  // 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. Det slår ut y-överflödet på kodblocket och sätter ikonen längst ner som jag inte ville ha. Så min är högst upp till höger.

Mina anpassningar

Huvudfunktionen

Insticksprogrammet krokar in i after:highlightElement händelse och lägger till en knapp i kodblocket.

Så först kopierade jag Faraz kod och gjorde sedan följande ändringar:

  1. Istället för att lägga till den till slutet av kodblocket förbereder jag den till början.
  2. Istället för SVG använde jag versionen BoxIcons genom att bara lägga till dessa klasser till den infogade knappen och ställa in textstorleken till text-xl.
  3. Jag tog bort rostat bröd meddelande och ersatte det med en enkel showToast funktion som jag har på min webbplats (se senare)
  4. Jag la till en aria-label och title till knappen för tillgänglighet (och för att ge en fin hover effekt).
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 Funktion

Detta beror på en rakkniv delvis jag lagt till i mitt projekt. Denna del använder DaisyUI Toast komponent för att visa ett meddelande till användaren. Jag gillar detta tillvägagångssätt eftersom det håller Javascript ren och enkel och tillåter mig att styla rostat budskap på samma sätt som resten av webbplatsen.

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

Du kommer att märka detta har också en udda gömd p tagga längst ner, detta är bara för Tailwind att tolka dessa klasser när det bygger webbplatsens CSS.

Javascript-funktionen är enkel, den visar bara rostat bröd meddelandet för en bestämd tid och sedan döljer det igen.

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

Vi kan sedan kalla detta med hjälp av showToast Funktionen hos copyButton.onclick händelse.

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

Jag lade till denna partiella rätt i toppen av min _Layout.cshtml fil så att den är tillgänglig på varje sida.

<partial name="_Toast"  />``

Nu när vi visar blogginlägg kodblocken har: Kopiera knapp

Slutsatser

Så det är allt, en enkel ändring av Faraz kod för att få det att fungera för mig. Jag hoppas att det här hjälper nån annan.

logo

©2024 Scott Galloway