73 lines
2.6 KiB
JavaScript
73 lines
2.6 KiB
JavaScript
|
(function () {
|
||
|
const copyIcon = document.getElementById("code-copy").innerHTML;
|
||
|
const copyIconDone = document.getElementById("code-copy-done").innerHTML;
|
||
|
|
||
|
/**
|
||
|
* code inspired by https://digitaldrummerj.me/hugo-add-copy-code-snippet-button/
|
||
|
* and https://www.dannyguo.com/blog/how-to-add-copy-to-clipboard-buttons-to-code-blocks-in-hugo
|
||
|
*/
|
||
|
|
||
|
function createCopyButton(highlightDiv) {
|
||
|
const button = document.createElement("button");
|
||
|
button.className = "right-1 top-1 absolute";
|
||
|
button.type = "button";
|
||
|
button.innerHTML = copyIcon;
|
||
|
button.addEventListener("click", () => copyCodeToClipboard(button, highlightDiv));
|
||
|
highlightDiv.insertBefore(button, highlightDiv.firstChild);
|
||
|
}
|
||
|
|
||
|
document.querySelectorAll(".highlight").forEach((highlightDiv) => createCopyButton(highlightDiv));
|
||
|
|
||
|
async function copyCodeToClipboard(button, highlightDiv) {
|
||
|
let codeToCopy = highlightDiv.querySelector("code").textContent;
|
||
|
if (highlightDiv.querySelector("table")) { // code with line number
|
||
|
codeToCopy = highlightDiv.querySelector("td:last-child code").textContent;
|
||
|
}
|
||
|
let permissionGranted = true;
|
||
|
try {
|
||
|
var result = await navigator.permissions.query({ name: "clipboard-write" });
|
||
|
if (result.state != "granted" && result.state != "prompt") {
|
||
|
permissionGranted = false;
|
||
|
}
|
||
|
} catch (_) {
|
||
|
// The clipboard-write permission name is not supported in Firefox, only Chromium browsers.
|
||
|
// default to true in case of error for firefox
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
if (permissionGranted) {
|
||
|
await navigator.clipboard.writeText(codeToCopy);
|
||
|
} else {
|
||
|
copyCodeBlockExecCommand(codeToCopy, highlightDiv);
|
||
|
}
|
||
|
} catch (_) {
|
||
|
copyCodeBlockExecCommand(codeToCopy, highlightDiv);
|
||
|
} finally {
|
||
|
/* Chrome doesn't seem to blur automatically,
|
||
|
leaving the button in a focused state. */
|
||
|
button.blur();
|
||
|
button.innerHTML = copyIconDone;
|
||
|
setTimeout(function () {
|
||
|
button.innerHTML = copyIcon;
|
||
|
}, 2000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function copyCodeBlockExecCommand(codeToCopy, highlightDiv) {
|
||
|
const textArea = document.createElement("textArea");
|
||
|
textArea.contentEditable = "true";
|
||
|
textArea.readOnly = "false";
|
||
|
textArea.className = "copyable-text-area";
|
||
|
textArea.value = codeToCopy;
|
||
|
highlightDiv.insertBefore(textArea, highlightDiv.firstChild);
|
||
|
const range = document.createRange();
|
||
|
range.selectNodeContents(textArea);
|
||
|
const sel = window.getSelection();
|
||
|
sel.removeAllRanges();
|
||
|
sel.addRange(range);
|
||
|
textArea.setSelectionRange(0, 999999);
|
||
|
document.execCommand("copy");
|
||
|
highlightDiv.removeChild(textArea);
|
||
|
}
|
||
|
})();
|