Add buttons to copy code snippets

This commit is contained in:
Helen Chong 2025-02-17 18:11:21 +08:00
parent 30bacfa6af
commit 79924b4d95
7 changed files with 84 additions and 1 deletions

View File

@ -37,6 +37,9 @@
{% if toc %}
<script src="{{'/assets/js/details-utils.js'}}" defer></script>
{% endif %}
{% if hasCodeBlock %}
<script src="/assets/js/copycode.js" defer></script>
{% endif %}
{% if hasTooltips %}
<script src="/assets/js/tooltips.js" defer></script>
{% endif %}

View File

@ -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}

View File

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

58
src/assets/js/copycode.js Normal file
View File

@ -0,0 +1,58 @@
function createCopyBtn(blockIndex) {
return `<div class="cc-wrapper d-none d-sm-block">
<button class="cc-btn btn-muted shadow" title="Copy code" data-target="${blockIndex}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2"/><path d="M9 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z"/></svg>
Copy Code
</button>
</div>`;
}
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 = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" /><path d="M9 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z" /><path d="M9 14l2 2l4 -4" /></svg> 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);
})
})

View File

@ -0,0 +1,5 @@
---
date: 2025-02-17T18:10:52+0800
---
* Add buttons to copy code snippets to pages with code blocks.

View File

@ -1,3 +1,4 @@
export default {
tags: ["code snippets"]
tags: ["code snippets"],
hasCodeBlock: true
}

View File

@ -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)