拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Monkeytype 字体接入完全指南:从 woff2 字体文件到内置字体选择器的完整流程

Monkeytype 字体接入完全指南从 woff2 字体文件到内置字体选择器的完整流程【免费下载链接】monkeytypeThe most customizable typing website with a minimalistic design and a ton of features. Test yourself in various modes, track your progress and improve your speed.项目地址: https://gitcode.com/gh_mirrors/mon/monkeytype本篇指南围绕 Monkeytype 的字体扩展机制展开讲解如何向这一打字网站添加自定义字体包括字体文件的格式与命名规范、在 schema 中注册字体名称、在前端常量中声明字体映射以及最终通过 Pull Request 提交回上游的完整流程。读完本文你将掌握 Monkeytype 字体的底层数据结构KnownFontNameSchema与Fonts映射、字体在运行时如何被加载与回退--fontCSS 变量与font-face生成逻辑并能独立完成一次从零到一的字体贡献。准备工作Fork Monkeytype 仓库要向 Monkeytype 贡献字体第一步是在 GitHub 上创建该仓库的个人副本即 Fork。前往 Monkeytype 官方仓库页面点击页面右上角的Fork按钮即可在个人账号下生成一份独立于主仓库、可以自由修改的代码副本。后续的所有改动都在这份 fork 中进行最终通过 Pull Request 合并回上游。说明本仓库为 Monkeytype 的镜像副本贡献流程与上游一致你在本仓库中看到的源码路径如frontend/src/ts/constants/fonts.ts与上游保持一致。添加字体的完整三步流程Monkeytype 的字体接入共分为三个环节缺一不可将.woff2字体文件放入frontend/static/webfonts目录在packages/schemas/src/fonts.ts的KnownFontNameSchema枚举末尾注册字体名在frontend/src/ts/constants/fonts.ts的Fonts对象末尾声明该字体对应的配置文件。下面逐一展开。第一步准备并放置字体文件将你的字体文件放入frontend/static/webfonts目录例如My-Font.woff2。该目录集中存放了项目内置的全部字体文件当前仓库中已有 42 个.woff2文件供 SCSS 编译出的font-face规则引用。放置时需严格遵守两条命名规范必须是.woff2格式。Monkeytype 只内联 woff2 字体WOFF2 压缩率高、加载快适合 Web 场景其他格式如 ttf、otf不会被内置文件名不能包含空格也不能以数字开头。这是因为后续 schema 中的枚举名、CSS 选择器与 URL 引用都需要一个合法、可预测的标识符。第二步在 schema 中注册字体名称打开packages/schemas/src/fonts.ts在KnownFontNameSchema的 z.enum 列表末尾追加新的字体名例如const KnownFontNameSchema z.enum( [ Roboto_Mono, Noto_Naskh_Arabic, // ... 其他字体 My_Font, ], { errorMap: customEnumErrorHandler(Must be a known font family), }, );这里的要点在于字体名使用下划线_而非空格例如Roboto_Mono、JetBrains_Mono。如果你想让用户看到 My Font 这样的显示名可通过下文FontConfig.display字段实现不能以数字开头枚举名会作为前端常量对象的键使用必须追加在列表末尾保证既有枚举成员的顺序稳定避免因索引变化影响已存储的用户配置。从当前仓库源码看KnownFontNameSchema已收录 43 种字体Roboto_Mono、Noto_Naskh_Arabic、Source_Code_Pro、Fira_Code、JetBrains_Mono、Cascadia_Mono、CommitMono、Geist_Mono、Iosevka、Space_Grotesk等并配套了自定义错误处理器errorMap: customEnumErrorHandler(Must be a known font family),当配置值不在枚举内时会抛出 Must be a known font family 的明确报错。该 schema 同时导出了两个关键类型KnownFontNamez.infertypeof KnownFontNameSchema即内置字体名的联合类型FontNameSchemaKnownFontNameSchema.or(z.string().max(50).regex(/^[a-zA-Z0-9_\-.]$/))它在前端命令行的自定义字体输入中扮演校验角色——用户输入的自定义字体名最长 50 字符且仅允许字母、数字、下划线、连字符、加号和点号。schema包是整个类型契约的源头frontend/src/ts/config/metadata.tsx中fontFamily配置项的optionsMetadata、packages/schemas/src/languages.ts中语言文件的preferredFont字段类型为KnownFontNameSchema.optional()都引用了这里。因此新增字体时schema 的注册是第一步否则 TypeScript 编译阶段就会报错。第三步在 Fonts 常量中声明字体配置打开frontend/src/ts/constants/fonts.ts在文件末尾的Fonts对象中追加配置注意保持类型与既有条目一致export const Fonts: RecordKnownFontName, FontConfig { // ... 既有字体 My_Font: { fileName: My-Font.woff2, }, };Fonts的类型是RecordKnownFontName, FontConfig它要求每个 schema 枚举名都必须有对应的配置项——这也是为什么改 schema 不改常量会直接编译失败两步必须成对完成。FontConfig的完整类型定义如下见 frontend/src/ts/constants/fonts.tsexport type FontConfig { display?: string; weight?: number; } ( | { systemFont: true; fileName?: never; } | { systemFont?: never; fileName: string; } );各字段含义与取值规则字段类型作用取值参考源码实例fileNamestring必填除非systemFont字体文件相对于frontend/static/webfonts目录的文件名用于生成font-face的srcRoboto_Mono→RobotoMono-Regular.woff2displaystring可选覆盖在设置界面与命令行中显示的字体名称不设置时默认显示枚举名下划线会被替换为空格Boon→Boon (ไทย)Proto→0xProtoNoto_Sans_Lao→Noto Sans Lao (ລາວ)weightnumber可选声明字体的字重写入font-face的font-weight不设置时默认为 400IBM_Plex_Sans→600Nunito→700Geist/Geist_Mono→500MediumsystemFonttrue可选标记该字体使用操作系统内置字体此时不得再提供fileNameComic_Sans_MSdisplay: Helvetica、Courier、Georgia结合frontend/src/styles/fonts.scss可以看清这些配置如何落地为真实的 CSS。SCSS 通过each $font, $config in $fonts循环为每个字体生成两条font-face规则font-face { font-family: #{$font}; font-style: normal; font-weight: map-get($config, weight); font-display: block; src: url(/#{$dir}/#{map-get($config, src)}) format(woff2); }第一条使用常规目录webfonts对应正式加载第二条使用webfonts-preview目录font-family为Font Preview对应设置界面中的预览场景由 vite 插件 font-preview.ts 负责把字体拷贝到预览目录。这解释了为什么预览字体与实际测试字体可以走两套加载路径此外SCSS 中还硬编码了一条Vazirharf字体的font-face它是回退链的一部分见下文运行时机制。font-display: block意味着字体加载完成前文字保持不可见从而避免 FOUT未换字体时的闪烁。运行时机制字体如何被真正应用添加字体后前端在运行时通过以下链路应用字体见 frontend/src/ts/ui.ts 的applyFontFamily读取Config.fontFamily默认值为Roboto_Mono见 default-config.ts并把下划线替换为空格得到字体族名检查用户是否通过命令行上传了本地字体存储在LocalFontFamilyFile若存在则用font-face动态注册LOCALCUSTOM字体族并完全覆盖配置字体读取当前语言Config.language对应的语言文件若其声明了preferredFont则将其加入回退链例如阿拉伯语偏好Noto_Naskh_Arabic拼装最终的回退链并写入根元素的 CSS 变量--font: 配置字体, 语言偏好字体, Roboto Mono, Vazirharf, monospace;--font变量被 core.scss 等样式文件以font-family: var(--font)的方式消费因此一处设置即可作用于整个页面。字体选择器预览功能previewFontFamily则直接内联覆盖--font松开预览后自动还原。前端还提供了命令行的字体相关操作见 font-family.ts其中包括自定义字体名输入任意满足FontNameSchema校验的名称最长 50 字符仅允许[a-zA-Z0-9_\-.]实际生效前提是该字体已安装到用户操作系统上传本地字体通过文件选择器导入woff/woff2/ttf/otf格式文件校验 MIME 类型与扩展名后以 Data URL 形式存入FileStorage移除本地字体删除已上传的本地字体并重新应用配置字体。这些能力对贡献者意味着即便某个字体未被内置用户也能通过自定义字体名或本地字体上传获得相近体验——内置字体追求的是开箱即用与跨设备一致性。提交与创建 Pull Request完成上述改动后需要把成果合并回上游。推荐流程如下推送分支将包含新字体的改动提交并推送到你在第一步创建的 fork 仓库的某个分支同步上游在 fork 仓库页面先确保该分支与主仓库保持同步点击 Update branch避免合并冲突发起 PR点击 Contribute → Open pull request选择目标分支上游主分支与源分支你的字体分支在 PR 描述中说明新增字体的用途与来源等待维护者审查合并。提交前建议自查清单字体文件为.woff2格式位于frontend/static/webfonts且命名无空格、不以数字开头packages/schemas/src/fonts.ts的KnownFontNameSchema末尾已追加枚举名下划线命名frontend/src/ts/constants/fonts.ts的Fonts对象末尾已追加对应配置fileName与实际文件名一致必要时补充display/weight若字体属于系统内置字体如 macOS 自带字体应使用systemFont: true而非上传文件本地构建与测试通过设置页面的字体选择器中能看到新字体且测试界面实际生效。语言指南字体与语言的联动Monkeytype 的字体与语言体系深度耦合每个语言文件位于frontend/static/languages/可以通过preferredFont字段schema 定义见 packages/schemas/src/languages.ts声明该语言的最佳显示字体。例如泰文相关字体Boon的display名特意标注了 ไทย老挝语则对应Noto_Sans_Lao。因此如果你的新字体用于支持某个非拉丁文字语言如阿拉伯文、天城文、老挝文还应当参考仓库的 Language guidelines为对应语言文件补充或更新preferredFont使其在语言切换时自动进入字体的回退链保证这些文字在默认字体不覆盖字形的情况下依然可以正常渲染。小结Monkeytype 的字体扩展是一条清晰的三步链路字体文件静态资源→ schema 枚举类型契约→ 前端常量映射运行时配置再由fonts.scss自动生成font-face、由applyFontFamily拼装回退链完成加载。理解这条链路后你不仅可以顺畅地贡献新字体也能举一反三地理解FontNameSchema校验、systemFont机制、语言preferredFont联动等设计细节——这正是 Monkeytype 作为高度可定制打字网站的核心架构之一。【免费下载链接】monkeytypeThe most customizable typing website with a minimalistic design and a ton of features. Test yourself in various modes, track your progress and improve your speed.项目地址: https://gitcode.com/gh_mirrors/mon/monkeytype创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门