As @diliprk said, Prism has a copy to clipboard button plugin. However, the one used on the tutorials site uses custom code to generate the copy button. Here’s the relevant snippet:
function initCodeCopy() {
const codeBlocks = document.querySelectorAll('code[class*="language-"]');
codeBlocks.forEach((block) => {
const lang = parseLanguage(block);
const referenceEl = block.parentElement;
const parent = block.parentElement.parentElement;
const wrapper = document.createElement('div');
wrapper.className = 'code-wrapper';
parent.insertBefore(wrapper, referenceEl);
wrapper.append(block.parentElement);
const copyBtn = document.createElement('button');
copyBtn.setAttribute('class', 'copy-button');
copyBtn.setAttribute('data-lang', lang);
copyBtn.innerHTML = `${lang} <svg viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M7 6V3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-3v3c0 .552-.45 1-1.007 1H4.007A1.001 1.001 0 0 1 3 21l.003-14c0-.552.45-1 1.007-1H7zM5.003 8L5 20h10V8H5.003zM9 6h8v10h2V4H9v2z" fill="currentColor"/></svg>`;
wrapper.insertAdjacentElement('beforeend', copyBtn);
});
function parseLanguage(block) {
const className = block.className;
if (className.startsWith('language')) {
const [prefix, lang] = className.split('-');
return lang;
}
}
function copy(e) {
const btn = e.currentTarget;
const lang = btn.dataset.lang;
const text = e.currentTarget.previousSibling.children[0].textContent;
navigator.clipboard.writeText(text).then(
() => {
btn.innerHTML = `copied! <svg viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M7 6V3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-3v3c0 .552-.45 1-1.007 1H4.007A1.001 1.001 0 0 1 3 21l.003-14c0-.552.45-1 1.007-1H7zm2 0h8v10h2V4H9v2z" fill="currentColor"/></svg>`;
btn.setAttribute('style', 'opacity: 1');
},
() => alert('failed to copy'),
);
setTimeout(() => {
btn.removeAttribute('style');
btn.innerHTML = `${lang} <svg viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M7 6V3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-3v3c0 .552-.45 1-1.007 1H4.007A1.001 1.001 0 0 1 3 21l.003-14c0-.552.45-1 1.007-1H7zM5.003 8L5 20h10V8H5.003zM9 6h8v10h2V4H9v2z" fill="currentColor"/></svg>`;
}, 3000);
}
const copyButtons = document.querySelectorAll('.copy-button');
copyButtons.forEach((btn) => {
btn.addEventListener('click', copy);
});
}
initCodeCopy()