| |
| |
| |
| |
| |
|
|
| (function () { |
| 'use strict'; |
|
|
| |
| function initTabs() { |
| document.querySelectorAll('[data-code-tabs]').forEach((group) => { |
| const buttons = group.querySelectorAll('.code-tabs button'); |
| const panels = group.querySelectorAll('.code-panel'); |
| buttons.forEach((btn) => { |
| btn.addEventListener('click', () => { |
| const target = btn.dataset.tab; |
| buttons.forEach((b) => b.setAttribute('aria-selected', String(b === btn))); |
| panels.forEach((p) => p.setAttribute('data-active', String(p.dataset.tab === target))); |
| }); |
| }); |
| }); |
| } |
|
|
| |
| function initCopy() { |
| document.querySelectorAll('.code-panel').forEach((panel) => { |
| const wrap = panel.closest('.code-wrap'); |
| if (!wrap || wrap.querySelector('.code-copy')) return; |
| const btn = document.createElement('button'); |
| btn.className = 'code-copy'; |
| btn.type = 'button'; |
| btn.textContent = 'Copy'; |
| btn.setAttribute('aria-label', 'Copy code'); |
| btn.addEventListener('click', async () => { |
| try { |
| await navigator.clipboard.writeText(panel.innerText); |
| } catch (e) { |
| const ta = document.createElement('textarea'); |
| ta.value = panel.innerText; |
| document.body.appendChild(ta); ta.select(); |
| document.execCommand('copy'); document.body.removeChild(ta); |
| } |
| btn.textContent = 'Copied'; |
| setTimeout(() => (btn.textContent = 'Copy'), 1500); |
| }); |
| wrap.appendChild(btn); |
| }); |
| } |
|
|
| |
| function initScrollspy() { |
| const links = Array.from(document.querySelectorAll('.doc-toc a')); |
| if (!links.length || !('IntersectionObserver' in window)) return; |
| const map = new Map(); |
| const headings = []; |
| links.forEach((link) => { |
| const id = link.getAttribute('href'); |
| if (!id || !id.startsWith('#')) return; |
| const el = document.querySelector(id); |
| if (el) { map.set(el, link); headings.push(el); } |
| }); |
| const io = new IntersectionObserver( |
| (entries) => { |
| entries.forEach((entry) => { |
| const link = map.get(entry.target); |
| if (!link) return; |
| if (entry.isIntersecting) { |
| links.forEach((l) => l.removeAttribute('aria-current')); |
| link.setAttribute('aria-current', 'true'); |
| } |
| }); |
| }, |
| { rootMargin: '-30% 0px -60% 0px' } |
| ); |
| headings.forEach((h) => io.observe(h)); |
| } |
|
|
| function boot() { initTabs(); initCopy(); initScrollspy(); } |
| if (document.readyState === 'loading') { |
| document.addEventListener('DOMContentLoaded', boot); |
| } else { boot(); } |
| })(); |
|
|