Files
everything-is-suitable/everything-is-suitable-uniapp/scripts/iconfont-build.py
T
zhangxiang 810081ac0a feat: 小程序端 UI 优化与纯客户端化改造
- 移除微信订阅推送功能(云函数/订阅管理页),回归纯客户端零后端架构
- 新增今日黄历默认展示卡片 TodayAlmanacCard(9 语言翻译)
- i18n 修复:启用 globalInjection 修复 $t 未注入,插值消息全部改为
  Messages Functions 适配小程序端(63 处)
- 修复底部导航切换失效与运势页数据不刷新
- 统一设计令牌(深褐主色 + 印红强调色),组件 UI 规范重构
- 图标 iconfont 化(FontAwesome 子集化,修复 Android 豆腐块)
- 新增 postcss-px2rpx 机型自适应(仅 mp-weixin 构建生效)
- 新增 5 个用户旅程 E2E 测试(31 用例)与验收报告
- 补充微信小程序项目配置(appid)
2026-08-28 07:51:02 +08:00

135 lines
4.1 KiB
Python
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.
#!/usr/bin/env python3
"""
小程序 iconfont 生成工具(FontAwesome 子集化 + base64 输出)
用法: python3 scripts/iconfont-build.py <woff2路径> <输出css路径> [--names name1,name2,...]
示例: python3 scripts/iconfont-build.py node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2 src/styles/iconfont.css --names calendar,star,heart
功能:
1. 将 woff2 转为 ttf
2. 按 --names 指定的图标名子集化(保留最小字形,减小包体)
3. 生成 base64 内联 @font-face CSSfont-family: 'fa-icons'
4. 输出 unicode 映射 JSON(供 Icon 组件使用)
图标名 -> unicode 映射(FontAwesome v6 fa-solid):
"""
import sys
import json
import base64
import argparse
from pathlib import Path
from fontTools.ttLib import TTFont
from fontTools import subset
# FontAwesome v6 fa-solid 图标名 -> unicode 码点
ICON_NAMES = {
'arrow-up': 0xF062,
'arrow-down': 0xF063,
'arrow-left': 0xF060,
'arrow-right': 0xF061,
'check': 0xF00C,
'close': 0xF00D,
'right': 0xF054,
'checkbox-checked': 0xF14A,
'checkbox-unchecked': 0xF0C8,
'plus': 0xF067,
'minus': 0xF068,
'search': 0xF002,
'calendar': 0xF073,
'star': 0xF005,
'heart': 0xF004,
'settings': 0xF013,
'home': 0xF015,
'user': 0xF007,
'info': 0xF129,
'warning': 0xF071,
'refresh': 0xF021,
'download': 0xF019,
'upload': 0xF093,
'share': 0xF064,
'copy': 0xF0C5,
'delete': 0xF1F8,
'edit': 0xF044,
'filter': 0xF0B0,
'sort': 0xF0DC,
'export': 0xF14D,
'history': 0xF1DA,
'bookmark': 0xF02E,
'chevron-up': 0xF077,
'chevron-down': 0xF078,
'chevron-left': 0xF053,
'chevron-right': 0xF054,
}
def main():
parser = argparse.ArgumentParser(description='FontAwesome iconfont 子集化构建')
parser.add_argument('woff2', help='fa-solid woff2 字体路径')
parser.add_argument('output_css', help='输出 CSS 路径')
parser.add_argument('--names', help='逗号分隔的图标名(默认全部)')
parser.add_argument('--font-family', default='fa-icons', help='字体族名')
args = parser.parse_args()
# 解析图标名
if args.names:
names = [n.strip() for n in args.names.split(',') if n.strip()]
else:
names = list(ICON_NAMES.keys())
# 收集 unicode
unicodes = []
mapping = {}
missing = []
for n in names:
if n not in ICON_NAMES:
print(f'⚠️ 未知图标名: {n}'); continue
unicodes.append(ICON_NAMES[n])
mapping[n] = ICON_NAMES[n]
# 加载并验证 cmap
tmp_ttf = Path('/tmp/fa-icons-subset.ttf')
font = TTFont(args.woff2)
cmap = font.getBestCmap()
for n, cp in mapping.items():
if cp not in cmap:
missing.append(f'{n}(U+{cp:04X})')
if missing:
print(f'⚠️ 缺失字形: {", ".join(missing)}')
print(f'图标数: {len(mapping)}')
# 子集化
options = subset.Options()
options.desubroutinize = True
options.ignore_missing_glyphs = True
options.drop_tables += ['GSUB', 'GPOS', 'GDEF', 'kern', 'cmap'] if False else []
sub = subset.Subsetter(options=options)
sub.populate(unicodes=unicodes)
sub.subset(font)
font.save(str(tmp_ttf))
# base64
b64 = base64.b64encode(tmp_ttf.read_bytes()).decode()
print(f'子集 ttf: {(tmp_ttf.stat().st_size/1024):.0f}KB | base64: {(len(b64)/1024):.0f}KB')
# 生成 CSS
css = f"""/* 自动生成: scripts/iconfont-build.py —— FontAwesome 子集化图标字体(仅含所需字形) */
@font-face {{
font-family: '{args.font_family}';
src: url(data:font/ttf;charset=utf-8;base64,{b64}) format('truetype');
font-weight: normal;
font-style: normal;
}}
"""
out = Path(args.output_css)
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(css)
print(f'CSS 已生成: {out} ({len(css)/1024:.0f}KB)')
# 输出映射 JSON(供 Icon 组件)
json_path = Path(args.output_css).with_suffix('.json')
json_path.write_text(json.dumps(mapping, ensure_ascii=False, indent=2))
print(f'映射已生成: {json_path}')
if __name__ == '__main__':
main()