function detectType(url) { if (!url) return 'none'; try { new URL(url); } catch(e) { return 'none'; } const path = (new URL(url)).pathname.toLowerCase(); const ext = path.split('.').pop(); if (['jpg','jpeg','png','gif','webp','bmp','svg','avif'].includes(ext)) return 'image'; if (['mp4','webm','ogv','mov'].includes(ext)) return 'video'; if (['mp3','flac','wav','ogg','aac','opus','m4a'].includes(ext)) return 'audio'; if (/(?:youtube\.com\/watch\?.*v=|youtu\.be\/)([A-Za-z0-9_-]{11})/.test(url)) return 'youtube'; if (/vimeo\.com\/(\d+)/.test(url)) return 'vimeo'; return 'link'; } function ytId(url) { const m = url.match(/(?:v=|youtu\.be\/)([A-Za-z0-9_-]{11})/); return m ? m[1] : null; } function vimeoId(url) { const m = url.match(/vimeo\.com\/(\d+)/); return m ? m[1] : null; } function updatePreview(url) { const el = document.getElementById('preview-body'); const badge = document.getElementById('type-badge'); if (!url) { el.innerHTML = '
// no url set
'; badge.textContent = 'none'; badge.className = 'badge t-none'; return; } const type = detectType(url); badge.textContent = type; badge.className = 'badge t-' + type.replace(/:.*/, ''); const s = url.replace(/"/g, '%22'); let h = ''; if (type === 'image') h += '