/**
* mist-detail.ts — Mist detail page module.
*
* Responsibilities:
* 1. Copy artifact content to clipboard (toolbar button).
* 2. Copy embed snippets (iframe / script) from sidebar.
* 3. Copy-button visual feedback (check icon for 2s).
*/
// ── SVG icons ─────────────────────────────────────────────────────────────────
const COPY_ICON = ``;
const CHECK_ICON = ``;
// ── Generic clipboard helper ──────────────────────────────────────────────────
async function copyText(text: string): Promise {
try {
await navigator.clipboard.writeText(text);
return true;
} catch {
return false;
}
}
function flashButton(btn: HTMLElement, originalHtml: string): void {
btn.innerHTML = `${CHECK_ICON} Copied`;
btn.classList.add('is-copied');
setTimeout(() => {
btn.innerHTML = originalHtml;
btn.classList.remove('is-copied');
}, 2000);
}
// ── Copy artifact content ─────────────────────────────────────────────────────
function bindCopyContent(): void {
const btn = document.querySelector('[data-action="copy-content"]');
if (!btn) return;
const originalHtml = btn.innerHTML;
btn.addEventListener('click', async () => {
const code = document.getElementById('artifact-content');
const text = (code?.textContent ?? '').trimEnd();
const ok = await copyText(text);
if (ok) flashButton(btn, originalHtml);
});
}
// ── Copy embed snippets ───────────────────────────────────────────────────────
function bindCopyEmbeds(): void {
document.querySelectorAll('[data-action="copy-embed"]').forEach(snippet => {
const copyBtn = snippet.querySelector('.ms-embed-copy');
const codeEl = snippet.querySelector('.ms-embed-code');
if (!copyBtn || !codeEl) return;
const originalHtml = copyBtn.innerHTML;
const doCopy = async () => {
// Decode HTML entities in the code element's text content
const text = codeEl.textContent ?? '';
const ok = await copyText(text);
if (ok) flashButton(copyBtn, originalHtml);
};
copyBtn.addEventListener('click', (e) => { e.stopPropagation(); void doCopy(); });
snippet.addEventListener('click', () => { void doCopy(); });
});
}
// ── Markdown heading anchors ──────────────────────────────────────────────────
function initMarkdownAnchors(): void {
const container = document.querySelector('.blob2-markdown');
if (!container) return;
container.querySelectorAll('h1,h2,h3,h4,h5,h6').forEach(heading => {
const slug = heading.id;
if (!slug) return;
const anchor = document.createElement('a');
anchor.href = '#' + slug;
anchor.className = 'blob2-md-anchor';
anchor.textContent = '#';
anchor.setAttribute('aria-hidden', 'true');
heading.appendChild(anchor);
});
}
// ── Entry point ───────────────────────────────────────────────────────────────
export function initMistDetail(_data?: Record): void {
bindCopyContent();
bindCopyEmbeds();
initMarkdownAnchors();
}