1(function () { 2 function formatSummaryLabel(count) { 3 var n = Math.max(0, parseInt(count, 10) || 0); 4 5 if (n <= 0) { 6 return 'kommentare'; 7 } 8 9 if (n === 1) { 10 return '1 kommentar'; 11 } 12 13 return n + ' kommentare'; 14 } 15 16 function getIssoHost() { 17 var script = document.querySelector('script[data-isso][src*="embed"]'); 18 19 return script && script.dataset.isso ? script.dataset.isso.replace(/\/$/, '') : null; 20 } 21 22 function readFederatedCountAttr(el) { 23 if (!el) { 24 return null; 25 } 26 27 return el.getAttribute('data-federated-count'); 28 } 29 30 function readCountAttr(el, name) { 31 if (!el) { 32 return null; 33 } 34 35 return el.getAttribute(name); 36 } 37 38 function getInstagramCommentCount(summary, thread) { 39 if (thread && typeof thread._wirresInstagramCount === 'number') { 40 return thread._wirresInstagramCount; 41 } 42 43 var raw = readCountAttr(thread, 'data-instagram-count') 44 || readCountAttr(summary, 'data-instagram-count') 45 || '0'; 46 47 return Math.max(0, parseInt(raw, 10) || 0); 48 } 49 50 function getAddonCommentCount(summary, thread) { 51 return getFederatedCommentCount(summary, thread) + getInstagramCommentCount(summary, thread); 52 } 53 54 function getFederatedCommentCount(summary, thread) { 55 if (thread && typeof thread._wirresFederatedCount === 'number') { 56 return thread._wirresFederatedCount; 57 } 58 59 var raw = readFederatedCountAttr(thread) 60 || readFederatedCountAttr(summary) 61 || '0'; 62 63 return Math.max(0, parseInt(raw, 10) || 0); 64 } 65 66 function countIssoCommentsInDom(thread) { 67 var root = thread.querySelector('#isso-root'); 68 69 if (!root) { 70 return 0; 71 } 72 73 return root.querySelectorAll('.isso-comment').length; 74 } 75 76 function applySummaryTotal(summary, thread, issoCount) { 77 var addonCount = getAddonCommentCount(summary, thread); 78 79 summary.textContent = formatSummaryLabel( 80 Math.max(0, parseInt(issoCount, 10) || 0) + addonCount 81 ); 82 } 83 84 function refreshIssoSummary() { 85 var summary = document.querySelector('[data-isso-summary]'); 86 var thread = document.getElementById('isso-thread'); 87 var host = getIssoHost(); 88 89 if (!summary || !thread) { 90 return; 91 } 92 93 var threadId = summary.dataset.threadId || thread.dataset.issoId; 94 95 if (!threadId || !host) { 96 applySummaryTotal(summary, thread, countIssoCommentsInDom(thread)); 97 return; 98 } 99 100 fetch(host + '/count', { 101 method: 'POST', 102 headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, 103 body: JSON.stringify([threadId]), 104 }) 105 .then(function (response) { 106 return response.ok ? response.json() : null; 107 }) 108 .then(function (counts) { 109 if (!Array.isArray(counts)) { 110 applySummaryTotal(summary, thread, countIssoCommentsInDom(thread)); 111 return; 112 } 113 114 applySummaryTotal(summary, thread, counts[0]); 115 }) 116 .catch(function () { 117 applySummaryTotal(summary, thread, countIssoCommentsInDom(thread)); 118 }); 119 } 120 121 function isIssoCommentHash(hash) { 122 return hash === 'kommentare' || /^isso-\d+$/.test(hash) || /^fediverse-/.test(hash) || /^webmention-/.test(hash); 123 } 124 125 function revealHiddenIssoComments(hash) { 126 var thread = document.getElementById('isso-thread'); 127 128 if (!thread || !hash) { 129 return false; 130 } 131 132 var safety = 0; 133 134 while (!document.getElementById(hash) && safety < 100) { 135 var loader = thread.querySelector('a.isso-load-hidden'); 136 137 if (!loader) { 138 break; 139 } 140 141 loader.click(); 142 safety += 1; 143 } 144 145 return !!document.getElementById(hash); 146 } 147 148 function tryReachIssoHash(hash) { 149 revealHiddenIssoComments(hash); 150 151 return scrollToIssoHashTarget(hash); 152 } 153 154 function highlightIssoTarget(el) { 155 var prev = document.querySelector('.isso-target'); 156 157 if (prev) { 158 prev.classList.remove('isso-target'); 159 } 160 161 var wrapper = el.querySelector ? el.querySelector('.isso-text-wrapper') : null; 162 163 (wrapper || el).classList.add('isso-target'); 164 } 165 166 function resolveIssoHashElement(hash) { 167 var target = document.getElementById(hash); 168 169 if (!target) { 170 return null; 171 } 172 173 if (/^isso-\d+$/.test(hash)) { 174 return target.classList.contains('isso-comment') 175 ? target 176 : (target.closest('.isso-comment') || target); 177 } 178 179 return target; 180 } 181 182 function scrollToIssoHashTarget(hash) { 183 if (!hash) { 184 return false;
185 } 186 187 var el = resolveIssoHashElement(hash); 188 189 if (!el) { 190 return false; 191 } 192 193 var rect = el.getBoundingClientRect(); 194 195 if (rect.height === 0 && rect.width === 0) { 196 el = el.parentElement || el; 197 } 198 199 el.scrollIntoView({ behavior: 'auto', block: 'start' }); 200 highlightIssoTarget(el); 201 202 return true; 203 } 204 205 function openCommentsDetails() { 206 var details = document.querySelector('.isso-wrap[data-section="comments"]'); 207 208 if (!details) { 209 return; 210 } 211 212 details.open = true; 213 214 try { 215 localStorage.setItem('beilage-comments', 'true'); 216 } catch (e) { 217 /* ignore */ 218 } 219 } 220 221 function watchIssoHashAnchor() { 222 var hash = window.location.hash.replace(/^#/, ''); 223 224 if (!isIssoCommentHash(hash)) { 225 return; 226 } 227 228 openCommentsDetails(); 229 230 if (tryReachIssoHash(hash)) { 231 return; 232 } 233 234 if (!/^fediverse-/.test(hash) && !/^webmention-/.test(hash) && !/^isso-\d+$/.test(hash)) { 235 return; 236 } 237 238 var thread = document.getElementById('isso-thread'); 239 240 if (!thread) { 241 return; 242 } 243 244 if (thread._issoHashStop) { 245 thread._issoHashStop(); 246 } 247 248 var attempts = 0; 249 var stop = function () { 250 clearInterval(interval); 251 observer.disconnect(); 252 thread._issoHashStop = null; 253 }; 254 255 thread._issoHashStop = stop; 256 257 var observer = new MutationObserver(function () { 258 if (tryReachIssoHash(hash)) { 259 stop(); 260 } 261 }); 262 263 observer.observe(thread, { childList: true, subtree: true }); 264 265 var interval = setInterval(function () { 266 if (tryReachIssoHash(hash) || ++attempts > 120) { 267 stop(); 268 } 269 }, 250); 270 } 271 272 function bustIssoLatestCache() { 273 fetch('/api/isso-latest-cache-clear', { 274 method: 'GET', 275 credentials: 'same-origin', 276 keepalive: true, 277 }).catch(function () { 278 /* ignore */ 279 }); 280 } 281 282 function initIssoSummary() { 283 var thread = document.getElementById('isso-thread'); 284 var summary = document.querySelector('[data-isso-summary]'); 285 286 if (!thread || !summary) { 287 return; 288 } 289 290 thread._wirresFederatedCount = getFederatedCommentCount(summary, thread); 291 thread._wirresInstagramCount = getInstagramCommentCount(summary, thread); 292 293 var lastIssoCommentCount = countIssoCommentsInDom(thread); 294 295 var debouncedRefresh = function () { 296 clearTimeout(thread._issoSummaryTimer); 297 thread._issoSummaryTimer = setTimeout(refreshIssoSummary, 400); 298 }; 299 300 var debouncedLatestCacheBust = function () { 301 clearTimeout(thread._issoLatestCacheTimer); 302 thread._issoLatestCacheTimer = setTimeout(function () { 303 var currentCount = countIssoCommentsInDom(thread); 304 305 if (currentCount !== lastIssoCommentCount) { 306 lastIssoCommentCount = currentCount; 307 bustIssoLatestCache(); 308 } 309 }, 800); 310 }; 311 312 var embed = document.querySelector('script[data-isso][src*="embed"]'); 313 314 if (embed) { 315 embed.addEventListener('load', function () { 316 setTimeout(watchIssoHashAnchor, 600); 317 }); 318 } 319 320 watchIssoHashAnchor(); 321 window.addEventListener('hashchange', watchIssoHashAnchor); 322 323 new MutationObserver(function () { 324 debouncedRefresh(); 325 debouncedLatestCacheBust(); 326 }).observe(thread, { 327 childList: true, 328 subtree: true, 329 }); 330 } 331 332 window.wirresRefreshIssoSummary = refreshIssoSummary; 333 334 if (document.readyState === 'loading') { 335 document.addEventListener('DOMContentLoaded', initIssoSummary); 336 } else { 337 initIssoSummary(); 338 } 339})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.