feat: 初始化画个标仓库 - AI驱动设计系统(BYOK模式) - 224源/371504图标+25海报源+130技能
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 临时调研:Iconify 官方集合 vs 本地已收录,找出未收录且许可证合规的候选源
|
||||
* 输出:未收录集合清单(id / 图标数 / license / 是否合规 / 收录价值初判)
|
||||
*/
|
||||
'use strict';
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = process.cwd();
|
||||
const SOURCES = require(path.join(ROOT, 'js', 'data', 'icon-sources.js'));
|
||||
|
||||
// 本地已收录的 iconify prefix(npm: '@iconify-json/xxx' 的 xxx)
|
||||
const localPrefixes = new Set();
|
||||
for (const s of SOURCES) {
|
||||
const m = String(s.npm || '').match(/@iconify-json\/([\w-]+)/);
|
||||
if (m) localPrefixes.add(m[1]);
|
||||
// 有些源 id 即 prefix
|
||||
localPrefixes.add(s.id);
|
||||
}
|
||||
|
||||
function fetch(url, redirects) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = https.get(url, { timeout: 60000 }, (res) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
const next = res.headers.location;
|
||||
if (next.startsWith('/')) return resolve(fetch('https://api.iconify.design' + next, (redirects || 0) + 1));
|
||||
return resolve(fetch(next, (redirects || 0) + 1));
|
||||
}
|
||||
if (res.statusCode !== 200) { reject(new Error('HTTP ' + res.statusCode)); res.resume(); return; }
|
||||
const chunks = [];
|
||||
res.on('data', (c) => chunks.push(c));
|
||||
res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.setTimeout(60000, () => { req.destroy(new Error('timeout')); });
|
||||
});
|
||||
}
|
||||
|
||||
(async () => {
|
||||
console.log('拉取 Iconify 官方集合列表…');
|
||||
const raw = await fetch('https://api.iconify.design/collections');
|
||||
const json = JSON.parse(raw);
|
||||
const all = Object.entries(json.collections || json);
|
||||
console.log('顶层键:', Object.keys(json).slice(0, 10).join(', '));
|
||||
|
||||
// 许可证过滤:排除 BY-SA / BY-NC / BY-ND / GPL / -NC-(兼容空格分隔形式)
|
||||
const badRe = /by[\s-]?sa|by[\s-]?nc|by[\s-]?nd|gpl|nc-|cc[\s-]?by[\s-]?nc/i;
|
||||
const missing = [];
|
||||
for (const [prefix, info] of all) {
|
||||
if (localPrefixes.has(prefix)) continue;
|
||||
const license = info.license ? info.license.title : 'unknown';
|
||||
const bad = badRe.test(license);
|
||||
missing.push({ prefix, total: info.total, license, bad, author: info.author && info.author.name });
|
||||
}
|
||||
|
||||
// 未收录 + 合规(或 license unknown 单独列出)
|
||||
const good = missing.filter(m => !m.bad);
|
||||
const bad = missing.filter(m => m.bad);
|
||||
good.sort((a, b) => b.total - a.total);
|
||||
bad.sort((a, b) => b.total - a.total);
|
||||
|
||||
console.log(`\n=== 官方集合总数: ${all.length} | 本地已收录 iconify prefix: ${localPrefixes.size} ===`);
|
||||
console.log(`\n=== 未收录 + 许可证合规(${good.length} 个)===\n`);
|
||||
for (const m of good) {
|
||||
console.log(` ${m.prefix.padEnd(28)} ${String(m.total).padStart(6)} ${m.license.padEnd(28)} ${m.author || ''}`);
|
||||
}
|
||||
console.log(`\n=== 未收录 + 许可证不合规(${bad.length} 个,仅供参考)===\n`);
|
||||
for (const m of bad.slice(0, 60)) {
|
||||
console.log(` ${m.prefix.padEnd(28)} ${String(m.total).padStart(6)} ${m.license.padEnd(28)} ${m.author || ''}`);
|
||||
}
|
||||
})().catch((e) => { console.error('❌', e.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user