(() => { const MAX = 120; const path = (el) => { const parts = []; let n = el; while (n && n.nodeType === 1 && parts.length < 5) { let s = n.tagName.toLowerCase(); if (n.id) { s += '#' + n.id; parts.unshift(s); break; } const cls = (n.className || '').toString().trim().split(/\s+/).filter(Boolean).slice(0, 3); if (cls.length) s += '.' + cls.join('.'); parts.unshift(s); n = n.parentElement; } return parts.join(' > '); }; const out = { url: location.href, title: document.title, visible: document.visibilityState, time: new Date().toISOString(), domSize: 0, badges: [], classHits: [], titleNumbers: [], iframes: [] }; try { const all = document.querySelectorAll('*'); out.domSize = all.length; // 1) small numeric nodes that look like an unread counter for (const el of all) { if (out.badges.length >= MAX) break; if (el.children.length > 1) continue; const txt = (el.textContent || '').trim(); if (!/^\d{1,4}\+?$/.test(txt)) continue; const r = el.getBoundingClientRect(); if (r.width < 6 || r.height < 6 || r.width > 140 || r.height > 60) continue; const cs = getComputedStyle(el); const bg = (cs.backgroundColor.match(/\d+/g) || []).map(Number); const fg = (cs.color.match(/\d+/g) || []).map(Number); const bgRed = bg.length >= 3 && bg[0] > 150 && bg[1] < 120 && bg[2] < 120; const fgRed = fg.length >= 3 && fg[0] > 150 && fg[1] < 110 && fg[2] < 110; out.badges.push({ p: path(el), t: txt, red: bgRed || fgRed, bg: cs.backgroundColor, color: cs.color, fs: cs.fontSize, rect: [Math.round(r.x), Math.round(r.y), Math.round(r.width), Math.round(r.height)], parentText: ((el.parentElement && el.parentElement.textContent) || '').trim().slice(0, 60) }); } // 2) nodes carrying unread-ish class names const sel = '[class*="unread"],[class*="badge"],[class*="Unread"],[class*="Badge"],[class*="red-dot"],[class*="redDot"],[class*="num"],[class*="count"],[class*="Count"]'; for (const el of document.querySelectorAll(sel)) { if (out.classHits.length >= MAX) break; const r = el.getBoundingClientRect(); const cs = getComputedStyle(el); out.classHits.push({ p: path(el), cls: (el.className || '').toString().slice(0, 160), t: (el.textContent || '').trim().slice(0, 40), bg: cs.backgroundColor, display: cs.display, rect: [Math.round(r.x), Math.round(r.y), Math.round(r.width), Math.round(r.height)] }); } // 3) numbers inside the tab title const tn = (document.title || '').match(/\d{1,4}/g) || []; out.titleNumbers = tn.slice(0, 6); // 4) frames (message panes are sometimes iframed) for (const f of document.querySelectorAll('iframe')) { out.iframes.push({ src: f.src || '', p: path(f) }); } } catch (e) { out.error = String(e && e.message || e); } return out; })()