88 lines
3.0 KiB
JavaScript
88 lines
3.0 KiB
JavaScript
(() => {
|
|
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;
|
|
})()
|