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
Een kopieerknop voor highlight.js
Saturday, 28 September 2024
Inleiding
Op deze site gebruik ik Hightlight.js om code knipsels client kant te renderen. Ik hou van dit als het houdt mijn server zijcode schoon en eenvoudig. Ik wilde echter een kopieerknop toevoegen aan elke code knipsel zodat gebruikers de code gemakkelijk konden kopiëren naar hun klembord. Dit is een eenvoudige taak, maar ik dacht dat ik het hier zou documenteren voor iedereen die hetzelfde zou willen doen.
Het doel
Het eindpunt is dat we een kopieerknop als deze op de site hebben:

OPMERKING: Alle krediet voor dit artikel gaat naar Faraz Patankar Wiens artikel ik gebruikte om deze te maken. Ik wilde alleen de wijzigingen die ik hier heb aangebracht vastleggen voor mijn eigen verwijzing en met anderen delen.
De opties
Er zijn een paar manieren om dit te doen; bijvoorbeeld is er een knopplugin kopiëren voor Higlight.js maar ik besloot dat ik meer controle wilde over de knop en de styling. Dus ik kwam... dit artikel voor het toevoegen van een kopieerknop.
De problemen
Terwijl dat artikel is een geweldige aanpak het had een paar problemen die stopte het perfect voor mij:
- Het maakt gebruik van een lettertype dat ik niet gebruik op mijn site (maar dan handmatig heeft de SVG ook, niet zeker waarom).
// 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>`;
Terwijl dit werkt, gebruik ik al BoxIcons op deze site die een kopieer pictogram er al in.
- Het maakt gebruik van een toastbibliotheek die ik niet heb op deze site.
// Notify user that the content has been copied
toast.success("Copied to clipboard", {
description: "The code block content has been copied to the clipboard.",
});
- Het schakelt de y-overflow uit op het codeblok en zet het pictogram onderaan wat ik niet wilde. Dus de mijne is rechtsboven.
Mijn aanpassingen
De belangrijkste functie
Deze plugin haken in de after:highlightElement event en voegt een knop toe aan het codeblok.
Dus eerst heb ik Faraz's code gekopieerd en daarna de volgende wijzigingen aangebracht:
- In plaats van het toe te voegen aan het einde van het code blok heb ik het aan het begin voorbereid.
- In plaats van de SVG heb ik de BoxIcons versie gebruikt door gewoon die klassen toe te voegen aan de ingevoegde knop en de textsize op te zetten
text-xl. - Ik verwijderde de toast notificatie en vervangen door een eenvoudige
showToastfunctie die ik heb in mijn site (zie later) - Ik voegde een
aria-labelentitleop de knop voor toegankelijkheid (en om een mooi zweefeffect te geven).
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 Functie
Dit berust op een scheermesdeel dat ik aan mijn project heb toegevoegd. Dit deel maakt gebruik van de DaisyUI Toast component om een bericht aan de gebruiker te tonen. Ik hou van deze aanpak als het houdt de Javascript schoon en eenvoudig en stelt me in staat om de toast bericht op dezelfde manier als de rest van de site te stijlen.
<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>
Je zult merken dat dit ook een vreemde verborgen heeft. p tag aan de onderkant, dit is gewoon voor Tailwind om deze klassen te ontleden wanneer het bouwt de site CSS.
De Javascript-functie is eenvoudig, het toont gewoon het toastbericht voor een bepaalde tijd en verbergt het dan opnieuw.
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);
}
We kunnen dit dan noemen met behulp van de showToast functie in de copyButton.onclick event.
showToast("The code block content has been copied to the clipboard.", 3000, "success");
Ik voegde deze gedeeltelijke recht aan de bovenkant van mijn _Layout.cshtml bestand dus het is beschikbaar op elke pagina.
<partial name="_Toast" />``
Nu wanneer we tonen blog posts de code blokken hebben:

Conclusie
Dus dat is het, een simpele wijziging in Faraz's code om het voor mij te laten werken. Ik hoop dat dit iemand anders helpt.