From 7fc9d978dd01d36b6f4460d6e99f896e16f166f2 Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Sat, 14 May 2022 20:27:10 +0200 Subject: [PATCH] Add copy button to all codeblocks --- layouts/posts/single.html | 12 ++++++++ static/src/js/code-copy.js | 61 ++++++++++++++++++++++++++++++++++++++ static/src/scss/style.scss | 31 +++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 layouts/posts/single.html create mode 100644 static/src/js/code-copy.js diff --git a/layouts/posts/single.html b/layouts/posts/single.html new file mode 100644 index 0000000..cc0d190 --- /dev/null +++ b/layouts/posts/single.html @@ -0,0 +1,12 @@ +{{ define "main" }} +
+
+ {{ partial "header_image.html" . }} + {{ partial "content.html" . }} +
+
+{{ end }} + +{{ define "scripts_extra" }} +{{ partial "script.html" "js/code-copy.js" }} +{{ end }} diff --git a/static/src/js/code-copy.js b/static/src/js/code-copy.js new file mode 100644 index 0000000..71e51f1 --- /dev/null +++ b/static/src/js/code-copy.js @@ -0,0 +1,61 @@ +(() => { + "use strict"; + + if (!document.queryCommandSupported("copy")) { + return; + } + + function flashCopyMessage(el, msg) { + el.textContent = msg; + setTimeout(() => { + el.textContent = "Copy"; + }, 1000); + } + + function selectText(node) { + let selection = window.getSelection(); + let range = document.createRange(); + if (node.childElementCount === 2) { + // Skip the title. + range.selectNodeContents(node.children[1]); + } else { + // ignore linenumbers + let _ln = node.getElementsByClassName("chroma"); + let _node = node.getElementsByTagName("pre")[1] + if (_ln.length >= 1) { + range.selectNodeContents(_node); + } else { + range.selectNodeContents(node); + } + } + selection.removeAllRanges(); + selection.addRange(range); + return selection; + } + + function addCopyButton(containerEl) { + let copyBtn = document.createElement("button"); + copyBtn.className = "copy-button"; + copyBtn.textContent = "Copy"; + + let codeEl = containerEl.firstElementChild; + copyBtn.addEventListener("click", () => { + try { + let selection = selectText(codeEl); + document.execCommand("copy"); + selection.removeAllRanges(); + + flashCopyMessage(copyBtn, "Copied!"); + } catch (e) { + console && console.log(e); + flashCopyMessage(copyBtn, "Failed :'("); + } + }); + + containerEl.appendChild(copyBtn); + } + + // Add copy button to code blocks + let highlightBlocks = document.getElementsByClassName("highlight"); + Array.prototype.forEach.call(highlightBlocks, addCopyButton); +})(); diff --git a/static/src/scss/style.scss b/static/src/scss/style.scss index 3b6cdef..56ca101 100644 --- a/static/src/scss/style.scss +++ b/static/src/scss/style.scss @@ -262,3 +262,34 @@ img { } } } + +.highlight { + position: relative; +} + +.copy-button { + position: absolute; + bottom: 7px; + right: 7px; + border: 0; + border-radius: 4px; + padding: 1px; + font-size: 0.7em; + line-height: 1.8; + color: #fff; + background-color: #666; + min-width: 55px; + text-align: center; +} + +.copy-button:hover { + background-color: #777; +} + +.highlight .copy-button { + display: none; +} + +.highlight:hover .copy-button { + display: inline; +}