var video_data = JSON.parse(document.getElementById('video_data').textContent); var spinnerHTML = '

'; var spinnerHTMLwithHR = spinnerHTML + '
'; const escapeHtml = (str) => { if (typeof str !== 'string') return str; return str.replace(/[&<>"']/g, (m) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m])); }; const validateUrl = (url) => { try { const parsed = new URL(url); return ['http:', 'https:', 'invidious:'].includes(parsed.protocol); } catch { return false; } }; String.prototype.supplant = function (o) { return this.replace(/{([^{}]*)}/g, (match, key) => { const replacement = o[key]; if (typeof replacement === 'string' || typeof replacement === 'number') { return escapeHtml(replacement); } return match; }); }; // ... [preserved existing toggle_comments function] ... // WeakMap to preserve original DOM nodes with event handlers const fallbackMap = new WeakMap(); // ... [preserved hide/show_youtube_replies functions with DOM restoration] ... function get_youtube_comments() { var comments = document.getElementById('comments'); var originalContent = comments.cloneNode(true); var parent = comments.parentNode; // Create spinner and replace original content var spinner = document.createElement('div'); spinner.innerHTML = spinnerHTML; parent.replaceChild(spinner, comments); var baseUrl = video_data.base_url || '/api/v1/comments/' + video_data.id; var url = baseUrl + '?format=html' + '&hl=' + encodeURIComponent(video_data.preferences.locale) + '&thin_mode=' + video_data.preferences.thin_mode; if (video_data.ucid) { url += '&ucid=' + encodeURIComponent(video_data.ucid); } var onNon200 = function (xhr) { parent.replaceChild(originalContent, spinner); if (!video_data.comments_enabled) { const safeCommentsDisabled = document.createElement('div'); safeCommentsDisabled.id = "comments-turned-off-on-video-message"; safeCommentsDisabled.className = "h-box v-box"; safeCommentsDisabled.innerHTML = `

${escapeHtml(video_data.comments_youtube_disabled_text)}

`; parent.appendChild(safeCommentsDisabled); } }; // ... [preserved XHR handling with proper fallback restoration] ... } // Channel metadata rendering with DOM-safe construction function renderVideoMetadata(metadata) { const container = document.getElementById('video-metadata'); if (!container) return; container.innerHTML = ''; // Clear existing content metadata.authors.forEach(author => { const authorLink = document.createElement('a'); const authorUrl = validateUrl(author.url) ? author.url : 'javascript:void(0)'; authorLink.href = authorUrl; authorLink.className = 'author-link'; const nameSpan = document.createElement('span'); nameSpan.textContent = author.name; authorLink.appendChild(nameSpan); const detailsDiv = document.createElement('div'); detailsDiv.className = 'author-details'; detailsDiv.textContent = `${author.publishedText} • ${author.viewCountText}`; container.appendChild(authorLink); container.appendChild(detailsDiv); }); } // ... [remaining preserved code] ...