Skip to content

Commit 4553303

Browse files
authored
docs: add copy env variables and labels to clipboard button (#46)
1 parent cf0649f commit 4553303

4 files changed

Lines changed: 124 additions & 0 deletions

File tree

docs/configuration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Configuration
22

3+
!!! tip
4+
5+
Hover over any variable or label to reveal a 'copy to clipboard' button
6+
37
## Environment Variables
48

59
### Required

docs/css/copy-to-clipboard.css

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
.copy-to-clipboard-wrapper {
2+
position: relative;
3+
display: inline-flex;
4+
align-items: center;
5+
gap: 8px;
6+
}
7+
8+
.copy-to-clipboard-button {
9+
background: none;
10+
border: none;
11+
padding: 4px;
12+
cursor: pointer;
13+
opacity: 0;
14+
transition: opacity 0.2s, color 0.2s;
15+
color: var(--md-typeset-color);
16+
line-height: 0;
17+
border-radius: 4px;
18+
}
19+
20+
.copy-to-clipboard-button:hover {
21+
background-color: var(--md-code-bg-color);
22+
color: var(--md-accent-fg-color);
23+
}
24+
25+
.copy-to-clipboard-wrapper:hover .copy-to-clipboard-button,
26+
.copy-to-clipboard-td:hover .copy-to-clipboard-button {
27+
opacity: 1;
28+
}
29+
30+
.copy-to-clipboard-button svg {
31+
width: 16px;
32+
height: 16px;
33+
fill: currentColor;
34+
}
35+
36+
.copy-to-clipboard-button.copy-success {
37+
color: #4CCD50;
38+
opacity: 1;
39+
}

docs/js/copy-to-clipboard.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* Subscribe to the document$ observable provided by MkDocs Material */
2+
document$.subscribe(function() {
3+
const codeElements = document.querySelectorAll("table td:first-child code");
4+
5+
codeElements.forEach(code => {
6+
if (code.closest(".copy-to-clipboard-wrapper")) return;
7+
8+
const td = code.closest("td");
9+
if (!td) return;
10+
11+
td.classList.add("copy-to-clipboard-td");
12+
13+
const wrapper = document.createElement("span");
14+
wrapper.classList.add("copy-to-clipboard-wrapper");
15+
16+
code.parentNode.insertBefore(wrapper, code);
17+
wrapper.appendChild(code);
18+
19+
const button = document.createElement("button");
20+
button.type = "button";
21+
button.setAttribute("aria-label", "Copy to clipboard");
22+
button.setAttribute("title", "Copy to clipboard");
23+
button.classList.add("copy-to-clipboard-button");
24+
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 21H8V7h11m0-2H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m-3-4H4a2 2 0 0 0-2 2v14h2V3h12V1Z"/></svg>';
25+
26+
wrapper.appendChild(button);
27+
28+
button.addEventListener("click", (e) => {
29+
e.preventDefault();
30+
e.stopPropagation();
31+
32+
const textToCopy = code.textContent.trim();
33+
34+
const fallbackCopy = () => {
35+
const textArea = document.createElement("textarea");
36+
textArea.value = textToCopy;
37+
textArea.style.position = "fixed";
38+
textArea.style.left = "-9999px";
39+
textArea.style.top = "0";
40+
document.body.appendChild(textArea);
41+
textArea.focus();
42+
textArea.select();
43+
try {
44+
document.execCommand('copy');
45+
return true;
46+
} catch (err) {
47+
console.error('Fallback copy failed', err);
48+
return false;
49+
}
50+
document.body.removeChild(textArea);
51+
};
52+
53+
if (navigator.clipboard && window.isSecureContext) {
54+
navigator.clipboard.writeText(textToCopy)
55+
.then(() => showSuccess(button))
56+
.catch(() => {
57+
if (fallbackCopy()) showSuccess(button);
58+
});
59+
} else if (fallbackCopy()) {
60+
showSuccess(button);
61+
}
62+
});
63+
});
64+
65+
function showSuccess(button) {
66+
const originalHTML = button.innerHTML;
67+
68+
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21 7 9 19l-5.5-5.5 1.41-1.41L9 16.17 19.59 5.59 21 7Z"/></svg>';
69+
button.classList.add("copy-success");
70+
71+
setTimeout(() => {
72+
button.innerHTML = originalHTML;
73+
button.classList.remove("copy-success");
74+
}, 1500);
75+
}
76+
});

mkdocs.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ nav:
1010
- Contributing: contributing.md
1111
extra_css:
1212
- css/theme.css
13+
- css/copy-to-clipboard.css
14+
extra_javascript:
15+
- js/copy-to-clipboard.js
1316
theme:
1417
name: material
1518
logo: assets/logo_icon.svg
@@ -58,7 +61,9 @@ extra:
5861
provider: mike
5962
markdown_extensions:
6063
- abbr
64+
- admonition
6165
- attr_list
66+
- pymdownx.details
6267
- pymdownx.emoji:
6368
emoji_index: !!python/name:material.extensions.emoji.twemoji
6469
emoji_generator: !!python/name:material.extensions.emoji.to_svg

0 commit comments

Comments
 (0)