diff --git a/sass/blog/main.scss b/sass/blog/main.scss
index ef76b91..2a3da05 100644
--- a/sass/blog/main.scss
+++ b/sass/blog/main.scss
@@ -85,3 +85,17 @@ $std-trans: 0.3s;
margin: 5px !important;
}
}
+
+.copy-code {
+ margin: auto;
+ margin-top: 0;
+ cursor: pointer;
+}
+
+.blog__content pre {
+ display: flex;
+}
+
+.blog__content code {
+ flex: auto;
+}
diff --git a/static/icons/check.svg b/static/icons/check.svg
new file mode 100644
index 0000000..09e07ea
--- /dev/null
+++ b/static/icons/check.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/static/icons/clipboard.svg b/static/icons/clipboard.svg
new file mode 100644
index 0000000..b02f56b
--- /dev/null
+++ b/static/icons/clipboard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/static/js/copy.js b/static/js/copy.js
new file mode 100644
index 0000000..7628faa
--- /dev/null
+++ b/static/js/copy.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 Aravinth Manivannan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+const check_dataset = (id, property) => {
+ let elem = document.getElementById(id);
+ if (elem === undefined || elem == null) {
+ console.warn(`${id} not found`);
+ return false;
+ }
+ if (!elem.dataset.hasOwnProperty(property)) {
+ console.warn(`${id} component doesn't have ${property} dataset attribute`);
+ return false;
+ }
+
+ return elem;
+};
+
+const init_clipboard = () => {
+ const CHECK_COMPONENT = check_dataset("check-icon", "check");
+ if (CHECK_COMPONENT == false) {
+ return;
+ }
+ const CHECK_ICON = CHECK_COMPONENT.dataset.check;
+
+ const CLIPBOARD_COMPONET = check_dataset("clipboard-icon", "clipboard");
+ if (CLIPBOARD_COMPONET == false) {
+ return;
+ }
+ const CLIPBOARD_ICON = CLIPBOARD_COMPONET.dataset.clipboard;
+
+ const copy_code = async (event) => {
+ const switch_clipboard_icon = async (event) => {
+ event.target.src = CHECK_ICON;
+ setTimeout(() => {
+ event.target.src = CLIPBOARD_ICON;
+ }, 1200);
+ };
+
+ let elem = event.target;
+ let codes = Array.from(elem.parentElement.getElementsByTagName("span"));
+ let content = "";
+ codes.forEach((span) => {
+ content = `${content} ${span.innerText}`;
+ });
+
+ await navigator.clipboard.writeText(content);
+ await switch_clipboard_icon(event);
+ };
+
+ const new_clipboard = () => {
+ let clipboard = document.createElement("img");
+ clipboard.src = CLIPBOARD_ICON;
+ clipboard.classList = ["copy-code"];
+ clipboard.addEventListener("click", copy_code);
+ return clipboard;
+ };
+
+ document.querySelectorAll("code").forEach((code) => {
+ if (code.parentElement.tagName == "PRE") {
+ code.parentElement.appendChild(new_clipboard());
+ }
+ });
+};
+
+init_clipboard();
diff --git a/templates/base.html b/templates/base.html
index 45f10b2..5ff84d4 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -16,6 +16,7 @@
href="{{ get_url(path='/mobile.css') }}"
/>
+
@@ -50,6 +51,8 @@
+
+
diff --git a/templates/blog/post.html b/templates/blog/post.html
index 2e73c1b..a6855aa 100644
--- a/templates/blog/post.html
+++ b/templates/blog/post.html
@@ -19,4 +19,5 @@ endblock meta %} {% block content %}
+
{% endblock content %}