Files
Scoreboard/vendor/fonts
AskaEth bc8b1ee6c0 feat: M3-M7 全模块落地 + 集成接线
- M3 认证/权限/审计/限流 + 全部 REST 接口
- M4 管理面板(MIUIx + 成绩录入/积分榜下钻/大屏控制)
- M5a 大屏页面(六页 + 明细覆盖层 + 缩放适配)
- M6 WebSocket 实时同步中心
- M7 xlsx 导出 + 赛事包 zip + 备份
- 规则包 YAML 导入导出(差异预览)
- 字体 vendor 子集化(4 套 x2 字重)
- 集成:realtime/export/rules 接入 main+httpapi;backup 子命令
- 修复:中间件包装 ResponseWriter 丢失 Hijacker,导致 WS 握手 501
2026-09-09 19:02:24 +08:00
..

vendor/fonts —— 本地字体(离线部署,禁止 CDN)

现场部署无外网,所有中文字体必须随仓库分发、从本目录本地加载。本目录只放子集化后的 woff2, 原始大字体(每套 8–12 MB)不入库。

字体清单

id 显示名 font-family 字重 单套合计
noto-sans Noto Sans SC Noto Sans SC 400 / 700 2.72 MB
noto-serif Noto Serif SC Noto Serif SC 400 / 700 3.71 MB
misans MiSans MiSans 400 / 700 1.76 MB
source-han-sans 思源黑体 Source Han Sans CN Source Han Sans CN 400 / 700 2.72 MB

合计 8 个 woff2、10.91 MB。逐文件体积与 sha256 见 manifest.json, 每个文件均 ≤ 4 MB / 套的目标(最大为 Noto Serif SC 的 3.71 MB)。

来源与授权

字体 来源 授权
Noto Sans SC Google Noto(~/Fonts/noto-sans/sc) SIL Open Font License 1.1
Noto Serif SC Google Noto(~/Fonts/noto-serif/sc/SubsetOTF/SC) SIL Open Font License 1.1
MiSans 小米(~/Fonts/MiSans/ttf) MiSans 字体知识产权许可协议
思源黑体 Source Han Sans CN Adobe(~/Fonts/思源黑体) SIL Open Font License 1.1

授权说明:本项目为内部赛事使用,不对外公开发布,字体授权不构成障碍 (见 devdocs/06-大屏端设计.md 9.1、devdocs/07-管理面板设计.md 9)。 若将来对外分发,需逐字体复核许可:Noto / 思源黑体为 OFL,可自由分发; MiSans 为厂商许可,公开分发前必须另行确认。OFL 字体保留其原始版权声明, 本目录未附 LICENSE 副本,需要时从 ~/Fonts/<字体目录>/LICENSE 取回。

子集化命令

依赖 fonttools + brotli(生成 woff2 必需):

pip install fonttools brotli
# 系统 Python 受 PEP 668 保护时,用带系统包的虚拟环境:
python3 -m venv --system-site-packages ~/.tmp/fontenv
~/.tmp/fontenv/bin/pip install brotli
PYTHON=~/.tmp/fontenv/bin/python vendor/fonts/tools/subset-fonts.sh

脚本会:生成字符集 → 逐字体跑 fontTools.subset → 重新生成 manifest.json。

子集字符集:ASCII 可打印字符 + GB2312 全部合法码位(一级 3755 + 二级 3008 汉字, 含全角标点、希腊/俄文、全角数字)+ 常用中文标点与数字符号,共 7553 字符。

子集化参数:

python -m fontTools.subset <源字体> \
  --flavor=woff2 \
  --layout-features='kern,liga,clig,calt,ccmp,locl,mark,mkmk' \
  --name-IDs='*' --name-languages='*' \
  --recommended-glyphs --drop-tables+=DSIG \
  --text="$(字符集)" --output-file=<id>-<weight>.woff2

去掉 CJK 竖排(vert/vrt2)等用不到的 OpenType 特性以压体积;保留 kern/liga 等排版特性。

如何使用

web/src/shared/styles/fonts.css 为每套字体写好 @font-face(font-display: swap) 与 --font-<id> 变量。在全局样式入口加一行即可生效:

@import './fonts.css';

CSS 里的 url() 是相对 web/src/shared/styles/ 的 ../../../../vendor/fonts/...。 Vite 构建时会把这些 woff2 作为资源打进产物(输出到 server/internal/webui/assets/), 运行时不再依赖仓库外的路径。

如何新增字体

  1. 把源字体(.otf/.ttf)放到 ~/Fonts/<目录>/(不要直接复制进仓库)。
  2. 在 tools/fonts.conf 追加一行:id|显示名|font-family|分类|授权|来源说明|Regular 源文件|Bold 源文件。
  3. 重跑 PYTHON=... vendor/fonts/tools/subset-fonts.sh,它会生成 <id>-regular.woff2、 <id>-bold.woff2 并更新 manifest.json。
  4. 在 web/src/shared/styles/fonts.css 补对应 @font-face 和 --font-<id> 变量。
  5. 检查单套合计 ≤ 4 MB;超了就精简字符集或换更轻的字重。

已知限制

  • MiSans 缺 ・(U+30FB,日文片假名中点,GB2312 内含),其余 7552 个字符齐全; 中文场景无影响。其余三套字符集全覆盖。
  • 只做 Regular + Bold 两档;如需 Medium/Light,按上节流程加字重(需扩展 fonts.conf 的字段格式)。
  • 字体文件已子集化,不要用原始 ~/Fonts 大字体覆盖本目录文件。