Files
drawlogo/audit-render.html
T

99 lines
4.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>图标渲染审计(真实浏览器 getBBox + 像素检测)</title>
<style>
body{font-family:monospace;font-size:12px;margin:8px;background:#111;color:#eee}
h2{font-size:14px}
.src{margin:6px 0;padding:6px;border:1px solid #333;border-radius:4px}
.src b{color:#7ee787}
.src .bad{color:#ff7b72}
</style>
</head>
<body>
<h1>全量渲染审计</h1>
<div id="out"><p>加载中…</p></div>
<h2>表情动画审计(独立审计页 audit-emojis.html,iframe 嵌入)</h2>
<iframe src="audit-emojis.html" style="width:100%;height:560px;border:1px solid #333;border-radius:4px;background:#111"></iframe>
<script>
const STROKE_SOURCES = new Set(['feather','lucide','tabler']);
function isStroke(ic, src){
if (ic.type && ic.type !== 'icon') return false;
return STROKE_SOURCES.has(src) || /stroke\s*=|\bstroke-linecap\s*=|\bstroke-linejoin\s*=/.test(ic.svg||'');
}
function applyAttrs(el, str){
const re = /([\w-]+)\s*=\s*"([^"]*)"/g;
let m;
while ((m = re.exec(str))) el.setAttribute(m[1], m[2]);
}
async function run(){
const out = document.getElementById('out');
const qs = new URLSearchParams(location.search);
const only = qs.get('only') ? qs.get('only').split(',').map(s=>s.trim()) : null;
const files = await (await fetch('/audit-files.json')).json();
const holder = document.createElement('div');
holder.style.cssText = 'position:fixed;left:-9999px;top:0;width:24px;height:24px;';
document.body.appendChild(holder);
let totalIcons = 0, totalBlank = 0, totalErr = 0;
const rows = [];
for (let fi = 0; fi < files.length; fi++) {
const f = files[fi];
const sid = f.replace(/\.js$/,'');
if (sid.startsWith('dicebear-')) continue;
if (only && !only.includes(sid)) continue;
let data = null;
try {
const txt = await (await fetch('/js/data/sources/' + f)).text();
const obj = txt.replace(/^[^\n]*?window\[[^\]]+\]\s*=\s*/, '').replace(/;\s*$/, '');
data = new Function('return (' + obj + ');')();
} catch(e){ totalErr++; rows.push({sid, error: '加载失败 ' + e.message}); continue; }
if (!data || !Array.isArray(data.icons)) { totalErr++; rows.push({sid, error:'无 icons 数组'}); continue; }
let blank = 0;
const samples = [];
for (const ic of data.icons) {
totalIcons++;
const preserve = ic.type && ic.type !== 'icon';
const isSt = preserve ? false : isStroke(ic, sid);
const attrs = isSt
? 'fill="none" stroke="#374151" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"'
: 'fill="#374151" stroke="none"';
const svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
svg.setAttribute('viewBox','0 0 24 24');
applyAttrs(svg, attrs);
let body = preserve ? ic.svg : (ic.svg||'')
.replace(/fill="currentColor"/g,'fill="inherit"')
.replace(/stroke="currentColor"/g,'stroke="inherit"');
svg.innerHTML = body;
holder.appendChild(svg);
let bb = null;
try { bb = svg.getBBox(); } catch(e){}
svg.remove();
const geoW = bb ? bb.width : 0, geoH = bb ? bb.height : 0;
// getBBox 为 0 → 无几何;或全部元素 opacity=0 / visibility=hidden → 视觉空白
const invisible = /opacity="0"|visibility="hidden"|display="none"/.test(body);
const visBlank = (geoW === 0 && geoH === 0);
if (visBlank || (invisible && !preserve)) {
blank++;
totalBlank++;
if (samples.length < 10) samples.push(ic.id + ' ' + (visBlank?'[无几何]':'[opacity0]'));
}
}
if (blank) rows.push({ sid, total: data.icons.length, blank, samples });
if (fi % 20 === 0) out.innerHTML = '<p>进度 ' + (fi+1) + '/' + files.length + ' …</p>';
await new Promise(r => setTimeout(r, 0));
}
let html = '<h2>扫描 ' + totalIcons.toLocaleString() + ' 个,空白 ' + totalBlank.toLocaleString() + ',加载失败 ' + totalErr + '</h2>';
rows.sort((a,b)=> (b.blank||0)-(a.blank||0)).forEach(r=>{
if (r.error) html += '<div class="src">✗ ' + r.sid + ':' + r.error + '</div>';
else html += '<div class="src"><b>' + r.sid + '</b>:<span class="bad">' + r.blank + '/' + r.total + '</span>(' + (r.blank/r.total*100).toFixed(2) + '%)' +
(r.samples.length ? '<br>' + r.samples.join('<br>') : '') + '</div>';
});
out.innerHTML = html;
document.title = 'AUDIT-DONE ' + totalIcons + '/' + totalBlank + '/' + totalErr;
}
run();
</script>
</body>
</html>