diff options
Diffstat (limited to 'assets/js/code-copy.js')
| -rw-r--r-- | assets/js/code-copy.js | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/assets/js/code-copy.js b/assets/js/code-copy.js new file mode 100644 index 0000000..8591436 --- /dev/null +++ b/assets/js/code-copy.js @@ -0,0 +1,79 @@ +(function () { + var LANG_NAMES = { + bash: 'Shell', sh: 'Shell', shell: 'Shell', zsh: 'Shell', + js: 'JavaScript', javascript: 'JavaScript', + ts: 'TypeScript', typescript: 'TypeScript', + go: 'Go', + py: 'Python', python: 'Python', + rs: 'Rust', rust: 'Rust', + html: 'HTML', + css: 'CSS', + toml: 'TOML', + yaml: 'YAML', yml: 'YAML', + json: 'JSON', + sql: 'SQL', + md: 'Markdown', markdown: 'Markdown', + c: 'C', + cpp: 'C++', 'c++': 'C++', + java: 'Java', + php: 'PHP', + ruby: 'Ruby', rb: 'Ruby', + swift: 'Swift', + kotlin: 'Kotlin', kt: 'Kotlin', + dockerfile: 'Dockerfile', + makefile: 'Makefile', + text: 'Text', txt: 'Text', + }; + + function prettyName(lang) { + if (!lang) return ''; + var key = lang.toLowerCase(); + return LANG_NAMES[key] || (lang.charAt(0).toUpperCase() + lang.slice(1)); + } + + function getCodeText(wrapper) { + var el = wrapper.querySelector('.lntd:last-child code') + || wrapper.querySelector('.code-body code') + || wrapper.querySelector('.code-body pre'); + return el ? el.innerText : ''; + } + + function initBlock(wrapper) { + var header = wrapper.querySelector('.code-header'); + if (header) { + var label = wrapper.querySelector('.code-lang-label'); + if (label) label.textContent = prettyName(header.getAttribute('data-lang') || ''); + } + + var btn = wrapper.querySelector('[data-copy-target]'); + if (!btn) return; + + btn.addEventListener('click', function () { + var text = getCodeText(wrapper); + if (!text) return; + + navigator.clipboard.writeText(text).then(function () { + var copyIcon = btn.querySelector('.icon-copy'); + var checkIcon = btn.querySelector('.icon-check'); + var liveRegion = wrapper.querySelector('.code-copy-status'); + if (copyIcon) copyIcon.classList.add('hidden'); + if (checkIcon) checkIcon.classList.remove('hidden'); + btn.classList.add('is-copied'); + if (liveRegion) liveRegion.textContent = 'Code copied to clipboard.'; + + setTimeout(function () { + if (copyIcon) copyIcon.classList.remove('hidden'); + if (checkIcon) checkIcon.classList.add('hidden'); + btn.classList.remove('is-copied'); + if (liveRegion) liveRegion.textContent = ''; + }, 2000); + }).catch(function () { + // silent fail for insecure contexts + }); + }); + } + + document.addEventListener('DOMContentLoaded', function () { + document.querySelectorAll('.code-block-wrapper').forEach(initBlock); + }); +})(); |
