feat: 初始化画个标仓库 - AI驱动设计系统(BYOK模式) - 224源/371504图标+25海报源+130技能

This commit is contained in:
sgp
2026-10-03 21:44:18 +08:00
commit 9e222877ea
497 changed files with 43611 additions and 0 deletions
+178
View File
@@ -0,0 +1,178 @@
// 采集可用字体 → _design-test/font-specimens.json
// 来源:① 本地素材库 OFL 字体(可商用) ② 本机已安装系统字体(仅预览)
// 说明:本机 Node / 浏览器均无外网,Google Fonts 无法拉取,故不含 Web 字体。
// 用法: node _design-test/harvest-fonts.js
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
// ── ① 本地素材库字体(js/data/posters/*.js,全部 OFL-1.1,可商用)──────
const LOCAL = [
{ id: 'league-spartan', family: 'League Spartan', cn: 'League Spartan · 几何无衬线', cat: '几何/无衬线', w: '700' },
{ id: 'fontsource-montserrat', family: 'Montserrat', cn: 'Montserrat · 几何无衬线', cat: '几何/无衬线', w: '800' },
{ id: 'fontsource-poppins', family: 'Poppins', cn: 'Poppins · 圆几何', cat: '几何/无衬线', w: '700' },
{ id: 'fontsource-inter', family: 'Inter', cn: 'Inter · 界面无衬线', cat: '几何/无衬线', w: '700' },
{ id: 'fontsource-space-grotesk', family: 'Space Grotesk', cn: 'Space Grotesk · 科技无衬线', cat: '科技/等宽', w: '700' },
{ id: 'fontsource-cinzel', family: 'Cinzel', cn: 'Cinzel · 罗马大写碑体', cat: '衬线', w: '700' },
{ id: 'fontsource-playfair', family: 'Playfair Display', cn: 'Playfair Display · 高对比衬线', cat: '衬线', w: '700' },
{ id: 'fontsource-lora', family: 'Lora', cn: 'Lora · 书卷衬线', cat: '衬线', w: '700' },
{ id: 'fontsource-oswald', family: 'Oswald', cn: 'Oswald · 窄体', cat: '窄体/粗黑', w: '500' },
{ id: 'fontsource-bebas-neue', family: 'Bebas Neue', cn: 'Bebas Neue · 高瘦大写字', cat: '窄体/粗黑', w: '400' },
{ id: 'fontsource-jetbrains-mono', family: 'JetBrains Mono', cn: 'JetBrains Mono · 等宽', cat: '科技/等宽', w: '700' },
{ id: 'fontsource-caveat', family: 'Caveat', cn: 'Caveat · 手写', cat: '手写/笔刷', w: '700' }
];
// ── ② 本机已安装字体(浏览器实测存在;仅作预览,商用需自行确认授权)────
// [字体名, 分类, 一句话特点]
const SYSTEM = [
// 几何 / 无衬线
['Helvetica', '几何/无衬线', '经典瑞士无衬线,Z 的中性标准'],
['Arial', '几何/无衬线', '最通用的无衬线'],
['Roboto', '几何/无衬线', 'Google 系统无衬线'],
['Segoe UI', '几何/无衬线', 'Windows 系统无衬线'],
['Tahoma', '几何/无衬线', '小字清晰的无衬线'],
['Verdana', '几何/无衬线', '宽字距、易读'],
['Trebuchet MS', '几何/无衬线', '带性格的旧金山体'],
['Calibri', '几何/无衬线', '圆角现代无衬线'],
['Candara', '几何/无衬线', '优雅的人文无衬线'],
['Corbel', '几何/无衬线', '开阔的人文无衬线'],
['Century Gothic', '几何/无衬线', '纯几何圆体'],
['Gill Sans MT', '几何/无衬线', '英式人文无衬线'],
['Franklin Gothic Book', '几何/无衬线', '美式哥特体(细)'],
['Franklin Gothic Medium', '几何/无衬线', '美式哥特体(中)'],
['Franklin Gothic Demi', '几何/无衬线', '美式哥特体(半粗)'],
['Microsoft Sans Serif', '几何/无衬线', 'Windows 经典 UI 体'],
['Tw Cen MT', '几何/无衬线', '二十世纪几何体'],
['Berlin Sans FB', '几何/无衬线', '有切角性格的展示无衬线'],
['Bahnschrift', '几何/无衬线', 'DIN 血统可变窄体'],
['Bahnschrift SemiBold', '几何/无衬线', 'DIN 血统(半粗)'],
['Arial Narrow', '窄体/粗黑', '压缩无衬线'],
['Arial Black', '窄体/粗黑', '超重无衬线'],
['Lucida Sans', '几何/无衬线', '宽圆无衬线'],
['Lucida Sans Unicode', '几何/无衬线', '宽圆无衬线(大字符集)'],
['Microsoft YaHei', '几何/无衬线', '微软雅黑(拉丁部分)'],
// 窄体 / 粗黑 / 展示
['Impact', '窄体/粗黑', '极致粗窄,Z 一坨重量'],
['Haettenschweiler', '窄体/粗黑', '超窄粗体'],
['Britannic Bold', '窄体/粗黑', '英式粗展示体'],
['Agency FB', '窄体/粗黑', '宽方现代展示体'],
['Wide Latin', '窄体/粗黑', '超宽衬线大字'],
['Goudy Stout', '窄体/粗黑', '极重衬线展示体'],
// 衬线
['Times New Roman', '衬线', '最经典衬线'],
['Georgia', '衬线', '屏幕衬线,笔画厚重'],
['Garamond', '衬线', '法式古典衬线'],
['Book Antiqua', '衬线', 'Palatino 血统'],
['Bookman Old Style', '衬线', '厚重书本衬线'],
['Cambria', '衬线', '屏幕阅读衬线'],
['Constantia', '衬线', '人文衬线'],
['Palatino Linotype', '衬线', '人文主义衬线'],
['Century Schoolbook', '衬线', '教科书衬线'],
['Century', '衬线', '古典几何衬线'],
['Calisto MT', '衬线', '过渡期衬线'],
['Bodoni MT', '衬线', '高对比 Didone,Z 斜画极细'],
['Elephant', '衬线', '超重衬线'],
['Engravers MT', '衬线', '刻版罗马大写'],
['Goudy Old Style', '衬线', '老式衬线'],
['High Tower Text', '衬线', '古籍感衬线'],
['Modern No. 20', '衬线', 'Didone 复古'],
['Perpetua', '衬线', ' Gill 的衬线体'],
['Perpetua Titling MT', '衬线', '大写标题衬线'],
['Poor Richard', '衬线', '美式老式衬线'],
['Castellar', '衬线', '碑体大写(带衬脚)'],
['Colonna MT', '衬线', '大写碑体'],
['Imprint MT Shadow', '衬线', '带阴影的碑体'],
['Niagara Engraved', '衬线', '镂空雕刻体'],
['Sylfaen', '衬线', '乔治亚衬线'],
['MS Gothic', '衬线', '日式黑体(拉丁窄)'],
['Yu Gothic', '几何/无衬线', '日式无衬线'],
// slab / 方正
['Rockwell', 'slab/方正', '几何板衬线,Z 方脚'],
['Rockwell Extra Bold', 'slab/方正', '超重板衬线'],
['Cooper Black', 'slab/方正', '圆胖粗衬线'],
// 装饰 / ArtDeco / 趣味
['Broadway', '装饰/趣味', 'ArtDeco 舞台体'],
['Showcard Gothic', '装饰/趣味', '手绘招牌体'],
['Stencil', '装饰/趣味', '模板喷字'],
['Onyx', '装饰/趣味', '超窄高对比'],
['Playbill', '装饰/趣味', '西部木牌体'],
['Algerian', '装饰/趣味', '异域装饰体'],
['Snap ITC', '装饰/趣味', '弹跳趣味体'],
['Juice ITC', '装饰/趣味', '手绘卡通体'],
['Magneto', '装饰/趣味', 'ArtDeco 霓虹体'],
['Jokerman', '装饰/趣味', '花哨趣味体'],
['Curlz MT', '装饰/趣味', '卷曲花体'],
['Chiller', '装饰/趣味', '惊悚手写体'],
['Pristina', '装饰/趣味', '细笔装饰体'],
['Harrington', '装饰/趣味', 'ArtDeco 装饰体'],
['Forte', '装饰/趣味', '笔刷装饰体'],
['Gigi', '装饰/趣味', '少女感装饰体'],
['Maiandra GD', '装饰/趣味', '圆角人文展示体'],
['Tempus Sans ITC', '装饰/趣味', '轻快展示体'],
['Papyrus', '装饰/趣味', '莎草纸手写体'],
['Old English Text MT', '装饰/趣味', '哥特黑体'],
['Viner Hand ITC', '手写/笔刷', '硬笔手写'],
// 手写 / 笔刷
['Brush Script MT', '手写/笔刷', '经典笔刷体'],
['Segoe Script', '手写/笔刷', '系统手写体'],
['Segoe Print', '手写/笔刷', '系统手写印刷体'],
['Freestyle Script', '手写/笔刷', '随性笔刷'],
['French Script MT', '手写/笔刷', '法式连笔'],
['Edwardian Script ITC', '手写/笔刷', '爱德华花体'],
['Palace Script MT', '手写/笔刷', '宫廷花体'],
['Script MT Bold', '手写/笔刷', '粗花体'],
['Vladimir Script', '手写/笔刷', '自由花体'],
['Bradley Hand ITC', '手写/笔刷', '手写便签体'],
['Kristen ITC', '手写/笔刷', '儿童手写体'],
['Lucida Handwriting', '手写/笔刷', '手写连笔'],
['Kunstler Script', '手写/笔刷', '德式装饰花体'],
['Ink Free', '手写/笔刷', '钢笔随手写'],
['Parchment', '手写/笔刷', '羊皮纸手写'],
['Vivaldi', '手写/笔刷', '斜体花体'],
['Comic Sans MS', '手写/笔刷', '手绘马克笔'],
// 等宽 / 科技
['Consolas', '科技/等宽', '编程等宽'],
['Cascadia Code', '科技/等宽', '微软编程等宽'],
['Cascadia Mono', '科技/等宽', '微软等宽'],
['Lucida Console', '科技/等宽', '经典等宽'],
['Courier New', '科技/等宽', '打字机等宽']
];
function pickLocalFile(files, want) {
const has = (re) => files.find(f => re.test(f));
return has(new RegExp('-latin-' + want + '-normal\\.woff2$'))
|| has(/-latin-400-normal\.woff2$/)
|| has(/-latin-\d+-normal\.woff2$/)
|| has(/-latin-.*normal\.woff2$/)
|| files.find(function (x) { return /\.woff2$/.test(x); }) || files[0];
}
const out = [];
let missing = 0;
for (const f of LOCAL) {
const p = path.join(ROOT, 'js', 'data', 'posters', f.id + '.js');
if (!fs.existsSync(p)) { console.log(' ✗ 缺源文件', f.id); missing++; continue; }
const t = fs.readFileSync(p, 'utf8');
const files = [...t.matchAll(/"file":"posters\/[^"]+\/([^"]+\.(?:woff2|woff|ttf|otf))"/g)].map(m => m[1]);
const latin = files.filter(x => /-latin-/.test(x));
const pick = pickLocalFile(latin.length ? latin : files, f.w);
if (!pick) { console.log(' ✗ 无 woff2', f.id); missing++; continue; }
out.push({
slug: f.id, family: f.family, cn: f.cn, cat: f.cat, weight: f.w,
kind: 'ofl', license: 'OFL-1.1 · 可商用',
fmt: (pick.split('.').pop() || 'woff2').toLowerCase(),
src: '../js/data/posters/' + f.id + '/files/' + pick
});
console.log(' ✓', f.family, '->', pick);
}
for (const [family, cat, cn] of SYSTEM) {
out.push({ slug: 'sys-' + family.toLowerCase().replace(/[^a-z0-9]+/g, '-'), family, cn, cat, weight: '', kind: 'system', license: '系统字体 · 商用需自行授权', src: '' });
}
console.log('本地 OFL 字体:', LOCAL.length - missing, '| 系统字体:', SYSTEM.length);
const cats = {};
out.forEach(f => { cats[f.cat] = (cats[f.cat] || 0) + 1; });
fs.writeFileSync(path.join(__dirname, 'font-specimens.json'),
JSON.stringify({ total: out.length, cats, fonts: out }, null, 0));
console.log('合计', out.length, '款 ·', JSON.stringify(cats));