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