From 79924b4d95449cca1b5b557a00ee3ea698174af2 Mon Sep 17 00:00:00 2001 From: Helen Chong <119173961+helenclx@users.noreply.github.com> Date: Mon, 17 Feb 2025 18:11:21 +0800 Subject: [PATCH] Add buttons to copy code snippets --- src/_includes/global/baselayout.njk | 3 + .../myarticles/accessible-footnotes.md | 1 + src/assets/css/components.css | 14 +++++ src/assets/js/copycode.js | 58 +++++++++++++++++++ src/changelogs/logs/2025/2025-02-17.md | 5 ++ src/projects/snippets/snippets.11tydata.js | 3 +- .../articles/juhani-lesbian-evidence.md | 1 + 7 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/assets/js/copycode.js create mode 100644 src/changelogs/logs/2025/2025-02-17.md diff --git a/src/_includes/global/baselayout.njk b/src/_includes/global/baselayout.njk index 659b8247..613df906 100644 --- a/src/_includes/global/baselayout.njk +++ b/src/_includes/global/baselayout.njk @@ -37,6 +37,9 @@ {% if toc %} {% endif %} + {% if hasCodeBlock %} + + {% endif %} {% if hasTooltips %} {% endif %} diff --git a/src/articles/myarticles/accessible-footnotes.md b/src/articles/myarticles/accessible-footnotes.md index f299ea89..7becde19 100644 --- a/src/articles/myarticles/accessible-footnotes.md +++ b/src/articles/myarticles/accessible-footnotes.md @@ -5,6 +5,7 @@ updated: 2024-12-03T23:51:27+0800 desc: "How I implement accessible footnotes, at least to the best of my ability. Written for 32-Bit Cafe's Community Code Jam #5." categories: ["32-bit cafe", "accessibility", "html", "css", "eleventy", "markdown-it"] toc: true +hasCodeBlock: true --- [![32-Bit Cafe "Back to School" Code Jam button](/assets/images/articles/accessible-footnotes/32bitcafe-backtoschool.png)](https://32bit.cafe/~xandra/events/codejam5/){.inline-img} diff --git a/src/assets/css/components.css b/src/assets/css/components.css index f44e669d..0ed1190d 100644 --- a/src/assets/css/components.css +++ b/src/assets/css/components.css @@ -103,6 +103,20 @@ a.link-btn[href^="http"]:not([href*="leilukin.com"]) { padding-right: calc(var(--btn-right-padding) + var(--sz-external-link)); } +/* Button to copy code snippets */ +.cc-btn { + font-size: 0.8em; + display: flex; + align-items: center; + gap: 0.2em; + margin-left: auto; + margin-right: 0; + border: 0.15em solid var(--clr-code-border); + border-radius: 0.2em; + background: var(--clr-link-btn-bg); + color: var(--clr-link-btn-txt); +} + /* Content Disclosure */ * + .content-disclosure { margin-top: var(--sz-paragraph-margin); } .content-disclosure__summary { font-weight: 700; } diff --git a/src/assets/js/copycode.js b/src/assets/js/copycode.js new file mode 100644 index 00000000..576abe7a --- /dev/null +++ b/src/assets/js/copycode.js @@ -0,0 +1,58 @@ +function createCopyBtn(blockIndex) { + return `
+ +
`; +} + +async function copyCode(block) { + const code = document.querySelector(`[data-block-id="${block}"]`); + const doCopy = async() => await navigator.clipboard.writeText(code?.innerText ?? ''); + + if (!navigator.userAgent.includes('Firefox')) { + const result = await navigator.permissions.query({ name: 'clipboard-write' }); + + if (result.state === 'granted' || result.state === 'prompt') { + doCopy(); + } + } else { + doCopy(); + } +} + +async function handleCopyBtnClick(event) { + const btn = event?.target; + const btnTarget = btn?.getAttribute('data-target'); + + if (btn && btnTarget) { + const originalText = btn.innerHTML; + + await copyCode(btnTarget); + + btn.innerHTML = ' Copied!'; + + setTimeout(() => { + btn.innerHTML = originalText; + }, 1500); + } +} + +document.addEventListener('DOMContentLoaded', () => { + const allCodeBlocks = Array.from(document.querySelectorAll('pre[class^="language-"]')); + + allCodeBlocks.forEach((b, i) => { + const code = b.childNodes[0]; + const codeBlockIndex = `cb-${i}`; + + b.insertAdjacentHTML('afterend', createCopyBtn(codeBlockIndex)); + code.setAttribute('data-block-id', codeBlockIndex); + }) + + const allCopyBtns = Array.from(document.querySelectorAll('.cc-btn')); + + allCopyBtns.forEach((btn) => { + btn.addEventListener('click', handleCopyBtnClick); + }) +}) \ No newline at end of file diff --git a/src/changelogs/logs/2025/2025-02-17.md b/src/changelogs/logs/2025/2025-02-17.md new file mode 100644 index 00000000..daa9cd4d --- /dev/null +++ b/src/changelogs/logs/2025/2025-02-17.md @@ -0,0 +1,5 @@ +--- +date: 2025-02-17T18:10:52+0800 +--- + +* Add buttons to copy code snippets to pages with code blocks. \ No newline at end of file diff --git a/src/projects/snippets/snippets.11tydata.js b/src/projects/snippets/snippets.11tydata.js index 13f5d2f3..7fc18c20 100644 --- a/src/projects/snippets/snippets.11tydata.js +++ b/src/projects/snippets/snippets.11tydata.js @@ -1,3 +1,4 @@ export default { - tags: ["code snippets"] + tags: ["code snippets"], + hasCodeBlock: true } \ No newline at end of file diff --git a/src/shrines/starwarskotor/articles/juhani-lesbian-evidence.md b/src/shrines/starwarskotor/articles/juhani-lesbian-evidence.md index d76052d9..771a13ed 100644 --- a/src/shrines/starwarskotor/articles/juhani-lesbian-evidence.md +++ b/src/shrines/starwarskotor/articles/juhani-lesbian-evidence.md @@ -5,6 +5,7 @@ updated: 2024-05-10 desc: "Juhani is a canon lesbian character and she has always been intended as such by the developers of Knights of the Old Republic. Here I am presenting evidence from the game files to prove it." tags: kotor 1 articles categories: ["star wars kotor"] +hasCodeBlock: true --- (Note: This article was originally published on Tumblr)