文风字体存储库

文风公开文件(网页字体包、许可原文、原件)的地址和布局,许可数据仓库的字段说明,以及收录和勘误。

文风字体存储库是什么

适合谁看:想直接读取文风公开文件(网页字体包、许可原文、字体原件)或许可数据的开发者、研究者和作者。

文风把每款字相关的公开文件放在固定地址,任何人都可以读取;许可的结构化数据另外放在一个公开的代码仓库里。这本书说明它们放在哪、怎么读。

两个部分

部分 在哪 放什么
公开文件 https://cn.windfonts.com/fonts-packages/{目录名}/… 网页字体包(CSS + woff2)、许可原文、可再分发字体的原件
许可数据仓库 github.com/Windfonts/font-licenses 每款字一份结构化许可信息(license-info.json),有原文的附许可原文

和别的网站的关系

不是每款字都有全部文件

所以程序里每个地址都要处理 404。

这本书的其他页

字体的几个标识:目录名、字体名和 ID

适合谁看:要在程序里关联同一款字的不同数据(网页、许可、接口)的开发者。

同一款字在不同地方有几种叫法。弄混了,地址就会 404、字体名就会写错。

目录名

目录名是一款字的短代号,例如霞鹜文楷是 xwwk,思源黑体是 syhtsc。

用在哪里 写法
字体页网址 app.windfonts.com/fonts/{目录名} 小写
公开文件地址 cn.windfonts.com/fonts-packages/{目录名}/… 小写
wenfeng.org 网址 /source/{目录名}/、/license/{目录名}/ 小写
许可数据仓库的文件夹 licenses/{目录名}/ 首字母大写,例如 Xwwk
license-info.json 里的 normalizedName 和仓库文件夹一致,首字母大写

比较目录名时请统一转成小写再比。拼文件地址时一律用小写。

字重名

公开文件地址里的字重目录,例如 Regular、Bold、ExtraLight,大小写要和字体页一致。个别字有自己的字重名(如 Normal、Text、Oblique)。

字重名和 CSS 里的 font-weight 数值没有固定对应关系,以 CSS 里实际写的为准。见《在 CSS 里使用:字体名、备用字体和多字重》。

CSS 里的字体名

网页字体包 CSS 里声明的 font-family 名字格式不统一(有 WF-、windfonts-、wenfeng- 等开头)。不要从目录名推算,要从 CSS 里读取。

字体 ID

元数据接口里每款字还有一个 ID(一长串字母数字)。按单款查询时,路径里写 ID 或目录名都可以,见《字体元数据 REST API(维护中)》。

许可数据字段说明

适合谁看:要读取 font-licenses 仓库里结构化许可信息的开发者和研究者。

文件在哪

font-licenses 仓库里,每款字一个文件夹:

licenses/{目录名}/license-info.json   结构化许可信息
licenses/{目录名}/LICENSE             许可原文(有才放)
schemas/license-info.schema.json      字段的 JSON Schema

文件夹名的大小写见《字体的几个标识:目录名、字体名和 ID》。

字段

字段定义见仓库里的 schemas/license-info.schema.json。几乎每个条目都有 normalizedName、type、commercial、verified,其余字段视情况而定。

字段 类型 说明
normalizedName 字符串 目录名
type 字符串 许可档位,如「开源商用」「免费商用」,见《许可档位与标签》
spdx 字符串 SPDX 标识,如 OFL-1.1、Apache-2.0;不是标准协议的可能为空
licenseUrl 字符串 许可原文或上游发布处的网址
licenseFile 字符串 仓库里许可原文文件的路径
commercial 布尔 能否商用
modification 布尔 / null 能否修改
distribution 布尔 / null 能否再分发字体文件
embedding 布尔 / null 能否嵌入文档或软件
webUse 布尔 / null 能否用作网页字体
attribution 布尔 / null 是否要求署名
shareAlike 布尔 / null 衍生作品是否要用同样的许可
purchaseUrl 字符串 付费字体的购买链接
price 数字 付费字体的价格(人民币)
notes 字符串 补充说明
verified 布尔 是否已人工核对
verifiedAt 字符串 核对日期
verifiedBy 字符串 依据什么核对
source 字符串 原文出处

部分条目还有的字段

字段 说明
licenseName 协议名称,如「某某体授权协议」
textState 原文归档状态:full 已归档全文,pointer 只记了出处链接,missing 还没找到原文
textSha256 归档原文的 SHA-256
rfn 保留字体名(衍生字体不能沿用的名字)
mustOfficial 是否必须到作者或厂商官方渠道下载
uses 几种具体用途是否允许:logo、trademark、video、doujin(同人)、print、appEmbed(嵌入 App)

读的时候注意

示例

{
  "normalizedName": "Xwwk",
  "type": "开源商用",
  "spdx": "OFL-1.1",
  "commercial": true,
  "modification": true,
  "distribution": true,
  "embedding": true,
  "webUse": true,
  "attribution": false,
  "shareAlike": false,
  "verified": true
}

(节选,省略了部分字段。)

接下来读什么

文件布局:网页字体包、许可原文和原件

适合谁看:要用程序读取文风公开文件的开发者。

所有公开文件都在 https://cn.windfonts.com/fonts-packages/{目录名}/ 下面,目录名一律小写。

一款字的目录

{目录名}/
├── {字重}/
│   ├── full/result.css        完整子集(每款字都有)
│   ├── zh/result.css          中文子集(有的字没有)
│   ├── zh-common/result.css   常用中文子集(有的字没有)
│   └── en/result.css          西文子集(有的字没有)
├── license/
│   ├── index.json             许可原文清单
│   └── original.txt           许可原文(有才放)
└── source/
    ├── index.json             原件清单
    └── …                      字体原件(许可允许再分发、并由文风托管的才有)

目录本身不能列出文件,请按清单里的文件名去取。

网页字体包

result.css 里是一组 @font-face,每条用 unicode-range 指向同目录下的一个 woff2 分片。用法见《网页字体地址规则》。

license/index.json

{
  "norm": "Xwwk",
  "kind": "license",
  "updated": "2026-10-04T21:07:15+08:00",
  "items": [
    {
      "role": "original",
      "primary": true,
      "file": "original.txt",
      "media": "text/plain; charset=utf-8",
      "bytes": 5171,
      "sha256": "…",
      "sourceUrl": "https://raw.githubusercontent.com/lxgw/LxgwWenKai/main/OFL.txt",
      "sourceName": "OFL.txt"
    }
  ]
}
字段 说明
items[].file 文件名,拼在 license/ 后面就是地址
items[].primary 是否主文件
items[].sha256 文件的 SHA-256
items[].sourceUrl 这份原文从哪里取的

source/index.json

{
  "norm": "xwwk",
  "kind": "source",
  "items": [
    {
      "file": "LXGWWenKai-Regular.ttf",
      "url": "https://cn.windfonts.com/fonts-packages/xwwk/source/LXGWWenKai-Regular.ttf",
      "bytes": 25575676,
      "sha256": "…",
      "status": "本站下载"
    }
  ]
}

status 的用词和 wenfeng.org 的下载状态一致,见《下载原件和切片:什么能下、怎么用》。

注意

怎么查一款字有没有某个字

适合谁看:要确认一段文字(人名、地名、繁体、生僻字)能不能用某款字完整显示的用户和开发者。

不写代码:字体页查字

打开字体页,在「字符表 · 查字」里输入你要用的文字。字体里没有的字会用虚线框标出来。

写代码:读 CSS 的 unicode-range

网页字体包 CSS 里每条 @font-face 都有 unicode-range,列出这一片包含哪些字的编码。把一份 result.css 里所有 unicode-range 合在一起,就是这一子集能显示的全部字符。 不在里面的字,浏览器会用备用字体显示。

下面是一个 Python 示例,检查一段文字在某款字的 full 子集里缺哪些字:

import re, urllib.request

def covered(css_url):
    req = urllib.request.Request(css_url, headers={"User-Agent": "Mozilla/5.0 (coverage-check)"})
    css = urllib.request.urlopen(req, timeout=30).read().decode("utf-8")
    cps = set()
    for rng in re.findall(r"unicode-range:([^;}]+)", css):
        for part in rng.split(","):
            part = part.strip().upper().removeprefix("U+")
            if "-" in part:
                a, b = part.split("-")
                cps.update(range(int(a, 16), int(b, 16) + 1))
            elif part:
                cps.add(int(part, 16))
    return cps

url = "https://cn.windfonts.com/fonts-packages/xwwk/Regular/full/result.css"
text = "你要检查的文字"
have = covered(url)
print("缺字:", "".join(ch for ch in set(text) if ord(ch) not in have and not ch.isspace()))

要点:

缺字怎么办

收录、勘误和提交新字体

适合谁看:想推荐文风收录某款字的用户,想上架自己作品的字体作者,以及发现许可信息有误的人。

文风收哪些字

wenfeng.org 写明了三道门槛,有一项过不去就不收录:

  1. 能取得完整许可原文。 发布包里的许可文件、官网许可页、官方仓库的 LICENSE,至少其一。
  2. 能对应到著作权人或发布厂商。 不收出处不明的转载包。
  3. 字体文件来自作者或厂商公布的渠道。 不收来路不明的打包文件。

许可还在核对的,目录里标「待核实」,核对完成前不提供文件、也不出证明。详见 我们怎么核验,以及《一款字体怎么收录上线》。

推荐一款字

写信到 license@wenfeng.org,写上:

WordPress 用户也可以看《提交新的中文字体》。

字体作者想上架自己的字

同样写信到 license@wenfeng.org,附上:

用开源协议(如 OFL)发布的字更容易收录:许可原文完整,网页字体和再分发的范围也清楚。

许可、作者、出处写错了

写信到 license@wenfeng.org,写清字体页或许可页的网址、哪里写错了、正确的依据(最好是许可原文链接)。你是权利人并对某个条目有异议的,请附上权利证明。

核实期间该条目会标为「待核实」,暂停出证、也不提供文件;确认有误就更正或下架。

文档写错了

写信到 docs@windfonts.com,写清页面标题和错误的地方。

接下来读什么