Overleaf Web 前端字体体系:fonts 目录的字体清单、构建脚本与 @font-face 集成实践
【免费下载链接】overleafA web-based collaborative LaTeX editor项目地址: https://gitcode.com/GitHub_Trending/ov/overleaf
本文基于 Overleaf 仓库中services/web/frontend/fonts/目录及其文档展开,系统梳理该目录收录的全部 11 个字体家族、自动获取字体并转换为 WOFF2 的构建脚本build-fonts.mjs的工作流程,以及各字体在前端源码中的实际挂载方式(@font-face声明、main-style.scss导入、编辑器/视觉主题中的调用点)。读完后你可以理解 Overleaf Web 端字体资源的组织方式,并掌握在其中新增、替换一个字体家族所需的完整改动链路。
一、fonts 目录定位与字体清单
字体说明文档 开篇即定义了该目录的职责:“This directory contains fonts used by the Overleaf web application.”(本目录包含 Overleaf Web 应用所使用的字体)。README 列出的 11 个字体家族与目录结构一一对应,每个家族一个子目录,内含 WOFF2 字体文件、一个@font-face声明 CSS 和对应的开源许可证文件:
| 字体家族 | 目录 | 上游来源 | 许可证文件 | 字体文件特点 |
|---|---|---|---|---|
| DM Mono | fonts/dm-mono/ | googlefonts/dm-mono | OFL.txt | Regular / Italic / Medium / MediumItalic 四款 woff2 |
| Inter | fonts/inter/ | rsms/inter v4.1 | LICENSE.txt | Regular / SemiBold |
| Lato | fonts/lato/ | latofonts.com(Lato 2 OFL Web 包) | OFL.txt | Latin 子集 Regular / Italic / Bold / BoldItalic |
| Material Symbols | fonts/material-symbols/ | google/material-design-icons | LICENSE.txt | 两个经过裁剪的变量字体切片(Filled / Unfilled) |
| Merriweather | fonts/merriweather/ | SorkinType/Merriweather | OFL.txt | Regular / Italic / Bold / BoldItalic |
| Noto Sans | fonts/noto-sans/ | notofonts.github.io(Latin/Greek/Cyrillic) | OFL.txt | 6 款静态字重(400/500/600 三档) |
| Noto Serif | fonts/noto-serif/ | notofonts.github.io(Latin/Greek/Cyrillic) | OFL.txt | 可变字体NotoSerif[wght].woff2及斜体可变版本 |
| OpenDyslexic Mono | fonts/open-dyslexic-mono/ | antijingoist/opendyslexic | OFL.txt | 单款 Regular(面向阅读障碍用户) |
| Open Sans | fonts/open-sans/ | googlefonts/opensans | OFL.txt | Light / Regular / SemiBold / Bold |
| Source Code Pro | fonts/source-code-pro/ | adobe-fonts/source-code-pro | LICENSE.md | 单款 Regular |
| STIX Two Math | fonts/STIXTwoMath/ | stipub/stixfonts | OFL.txt | 单款 Regular(数学字体) |
除inter/使用LICENSE.txt、source-code-pro/使用LICENSE.md、material-symbols/使用LICENSE.txt外,其余家族均携带 SIL Open Font License 的OFL.txt,与构建脚本中为各家族配置的license下载项一致。
二、字体获取与转换管线:build-fonts.mjs
构建脚本 是该目录的“上游工厂”,它负责从各字体的官方仓库拉取原始字体、转换为 WOFF2 并落盘许可证。核心结构是一个families配置数组,每个条目描述一个字体家族的获取方式:
const families = [ { folder: 'dm-mono', // 目标子目录 url: 'https://github.com/googlefonts/dm-mono', fonts: [ /* 直接下载的 ttf/woff2 文件 URL */ ], }, { folder: 'inter', url: 'https://github.com/rsms/inter/releases/tag/v4.1', archive: 'https://github.com/rsms/inter/releases/download/v4.1/Inter-4.1.zip', fonts: ['web/Inter-Regular.woff2', 'web/Inter-SemiBold.woff2'], // zip 内路径 license: 'https://raw.githubusercontent.com/.../LICENSE.txt', }, // ... 其余家族 ]脚本的下载与转换逻辑分三条路径:
- 直接下载:
fetchFile(url, path)用fetch拉取单文件并fs.writeFile落盘; - 压缩包提取:若家族配置了
archive(如 Inter 的发布 zip、Lato 的Lato2OFLWeb.zip),脚本把压缩包下载到系统临时目录(fs.mkdtemp(join(tmpdir(), 'fonts-'))),用yauzl以lazyEntries: true惰性遍历条目,只把fonts集合中列出的文件解压出来,写入family.folder/后删除临时 zip; - TTF 转 WOFF2:无论走哪条路径,只要落盘文件以
.ttf结尾,就执行execSync('woff2_compress "path"')压缩为同名.woff2,再fs.unlink删除原 TTF。脚本注释明确给出前置依赖:brew install woff2(脚本首行注释)。
最后,若家族配置了license字段,脚本同样下载许可证文件到该家族目录(例如 Merriweather 的OFL.txt、Source Code Pro 的LICENSE.md),这正是上文清单中各目录都带有许可证文件的原因。
这套管线解释了目录中的两个细节:noto-sans/下虽有 6 个 woff2,但build-fonts.mjs中 Noto Sans 的fonts数组列的正是对应的 6 个.ttf源文件;而source-code-pro/的上游源文件本身就叫SourceCodePro-Regular.ttf.woff2,故仓库中保留了这一“双层后缀”文件名。
三、@font-face 声明模式与 CSS 细节
每个字体子目录中都有一个与目录同名的 CSS(如 dm-mono.css),为每个字体文件声明一个@font-face规则。从这些 CSS 中可以归纳出 Overleaf 的几种典型声明模式:
1. 常规静态字体:逐字重声明font-family/font-style/font-weight。以 dm-mono.css 为例,DM Mono 声明了font-weight: 400(normal/italic)与font-weight: 500(normal/italic)共 4 个 face,并统一设置font-display: fallback:
@font-face { font-family: 'DM Mono'; font-style: normal; font-weight: 400; font-display: fallback; src: url('DMMono-Regular.woff2') format('woff2'); }2. 可变字体(variable font):noto-serif.css 是目录中唯一使用字体范围语法的声明,一个 face 覆盖整个字重区间并声明了字宽轴:
@font-face { font-family: 'Noto Serif'; font-style: normal; font-weight: 200 700; font-stretch: 62.5% 100%; src: url('NotoSerif[wght].woff2') format('woff2'); }3. 变量字体切片(icon font):material-symbols.css 声明了两个 face。第一个Material Symbols Rounded是官方可变字体MaterialSymbolsRounded[FILL,GRAD,opsz,wght].woff2在FILL 1, wght 400, GRAD 0, opsz 20固定值下生成的“切片”(注释中标明);第二个 face 的font-family必须写成Material Symbols Outlined——CSS 注释解释:原名 "Material Symbols Rounded Unfilled Partial" 不在 Firefox 的icon_font_allowlist白名单内,改名后才被 Firefox 允许作为图标字体渲染。未填充版本由frontend/fonts/material-symbols/build-unfilled.mjs生成(注释中指明)。
配套的.material-symbols类给出图标字体的标准用法:font-feature-settings: 'liga'启用连字以拼出图标名,并提供size-2x、rotate-180、unfilled(切换 FILL=0)三个修饰类。
4. 无障碍特例:open-dyslexic-mono.css 声明了ascent-override: 100%,用于修正该字体过高的 ascent 度量,避免行高异常。
5. 数学字体:stix-two-math.css 仅一个最简声明(family 名为Stix Two Math,未设置font-display),因为它是配合 MathJax/KaTeX 数学排版加载的数学字形来源,而非界面字体。
四、字体在前端代码中的实际挂载点
字体并非“下载即生效”,必须被样式系统导入并在代码中被引用。以 main-style.scss 为入口,其头部集中导入了 9 个字体 CSS(Noto Sans、Inter、DM Mono、Merriweather、Source Code Pro、STIX Two Math、Noto Serif、OpenDyslexic Mono、Material Symbols),注释标明这是 “Web fonts” 区块,紧随其后才是 vendor CSS 与 Bootstrap 引入。Lato 与 Open Sans 同样打包在本目录中,但不在该主样式入口的导入列表内,属于按需被其他样式文件引用的家族。
各字体在前端代码中的调用点可从源码中直接验证:
- STIX Two Math:源码编辑器的数学自动补全插件在 auto-complete.ts 中以
fontFamily: "'Stix Two Math', serif"渲染数学符号建议项; - Noto Serif:源码编辑器的工具栏面板在 toolbar-panel.ts 使用
'"Noto Serif", serif',视觉化编辑主题在 visual-theme.ts 中将其作为首选衬线字体('Noto Serif', 'Palatino Linotype', 'Book Antiqua', Palatino, serif !important)——这与 Overleaf 作为 LaTeX 编辑器的定位一致,衬线字体用于还原论文排版观感; - DM Mono:在 variable-overrides.scss 中被定义为全局等宽字体变量
$font-family-monospace: 'DM Mono', monospace,并在 foundations/typography.scss 中通过font-feature-settings启用其 “ss05”(stylistic set 5)变体,说明 Overleaf 利用的是 DM Mono 的可调字形特性而非仅其基础字形; - Inter:设计系统(DS)层在 ds/typography.scss 中把
--ds-font-family-sans设为'Inter',即新版界面组件的默认无衬线字体;其@font-face使用font-display: swap,与多数界面字体的fallback形成对比。
五、新增一个字体家族的完整改动链路
结合上述目录结构、构建脚本与样式入口,可以在 Overleaf 中新增字体家族的完整步骤是(仅描述操作方式,供二次开发参考):
- 下载与转换:在 build-fonts.mjs 的
families数组中新增一个条目,指定folder(目标子目录名)、字体源文件 URL(TTF 会被woff2_compress自动转为 WOFF2)或archive(zip 内路径列表),并按需给出license下载地址。本地运行前需安装woff2工具(brew install woff2,见脚本首行注释); - 编写声明 CSS:在该子目录内创建与目录同名的 CSS,按第三节所列模式声明
@font-face——静态字重逐档声明font-weight,可变字体使用font-weight: min max范围语法; - 接入样式系统:在 main-style.scss 的 “Web fonts” 区块以相对路径
@import '../fonts/<folder>/<folder>.css'引入(若仅在特定模块使用,也可放入对应模块样式中,参考 Lato/Open Sans 的用法); - 在代码/样式中引用:通过
font-family在 SCSS、CSS-in-JS 或组件 props 中挂载新字体,并确认所选font-display策略与用途匹配(界面文字常用swap/fallback,图标字体因需要连字完整性常用block)。
六、小结
services/web/frontend/fonts/目录以“一家族一目录、字体 + 声明 CSS + 许可证”的规整结构承载了 Overleaf Web 应用的全部 Web 字体;build-fonts.mjs将上游 TTF/zip 源统一转换为 WOFF2 并保留许可证,形成可复现的字体供应链;main-style.scss与各前端模块代码则分别把 Noto Sans/Inter/DM Mono 等界面字体、Noto Serif 衬线字体与 STIX Two Math 数学字体挂载到对应场景(全局排版、视觉化编辑主题、数学自动补全)。这套“清单文档 + 构建脚本 + @font-face CSS + 样式入口”的四件套,是理解并维护 Overleaf 前端字体体系的完整依据。
【免费下载链接】overleafA web-based collaborative LaTeX editor项目地址: https://gitcode.com/GitHub_Trending/ov/overleaf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考