feat: 初始化画个标仓库 - AI驱动设计系统(BYOK模式) - 224源/371504图标+25海报源+130技能
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user