0. 问题出现
Marp 是一个使用 Markdown 语法编写幻灯片的工具,非常适合用于快速创作版式美观但并不复杂的幻灯片。Marp 的官方 CLI 工具 marp-cli 支持将符合 Marp 格式的 Markdown 文件导出为 HTML 和 PDF 文件。然而,我最近在 macOS 上使用 marp-cli 导出 PDF 文件时,出现了中文字符缺失的问题,如下图所示:

经过一段时间的排查(以及与 Gemini 的讨论),我终于锁定了问题的原因,并找到了对应的解决方案。出乎我意料的是,虽然这个问题在 macOS 上可能广泛存在,但却似乎没有人记录过,因此我将解决方法记录于此,希望能够帮助到遇到同样问题的人。太长不看。
1. Marp 还是 Chrome?
面对中文字符渲染失败,我首先想到的是其中可能存在字体配置问题,但 macOS 对中文字体的支持应该(不论系统语言)非常完善才对。marp-cli 生成 PDF 的原理是,首先将 Markdown 文件转换为 HTML 文件,然后使用无头浏览器将 HTML 页面渲染为 PDF 文件,所以问题也可能出现在生成的 HTML 文件中。为了确认是否是在生成 HTML 时就出现了问题,我首先使用 marp-cli 生成了 HTML 文件,并使用浏览器打开,发现中文字符渲染正常:

并且可以发现,中文内容使用的是 macOS 内置的 PingFang 系列字体,按理说应该不存在任何问题:

看来浏览器一切正常?非也非也,一旦尝试使用 Chrome 把 HTML 打印成 PDF 文件,问题就又出现了。并且无论使用 Chrome 自己的打印功能,还是使用 macOS 系统的打印对话框,结果都是一样的:

这么看起来,marp-cli 应该没有问题,生成了正确的 HTML 文件。问题实际出现在 PDF 文件的生成过程中:不知为何,Chrome 未能正确渲染中文字符。
2. Chrome 还是 macOS?
虽然 HTML 和 PDF 的排版和渲染不是同一个引擎完成的,但字体查找和解析的逻辑应当是相同的才对,一个能够渲染而另一个不能就很奇怪了。是 PDF 渲染引擎没有能正确找到字体,还是找到了字体但是渲染失败了呢?最好的办法是使用「另一个 PingFang 字体」来验证一下。在 Markdown 文件中引用一份在线的 PingFang SC 试一试:
| |

中文字符可以正常渲染了!包括 macOS 系统的打印对话框也可以正常渲染中文字符。虽然在线的 PingFang SC 不一定和系统内置的 PingFang 字体完全一致,因而不能百分百地排除渲染引擎和字体之间的不兼容问题,但我们已经有很大的把握断定,问题出在字体查找的过程中——HTML 渲染和 PDF 渲染过程中,字体查找逻辑存在某个细小的差别,导致最终结果的不一致。
要继续排查下去,就要深入到 Chrome 的内部逻辑和日志中了,这将会是一项艰苦的工作。幸好见多识广的 Gemini 老师为我指明了一个未曾设想的方向:
既然网络字体能够完美解决,而本地字体在 Chrome 网页里显示正常、一进入 PDF 虚拟打印(无论是命令行还是 Chrome 自带的打印面板)就彻底失踪,这说明了一个非常关键的事实:
你的本地字体本身没有坏,Chrome 浏览器本身也能找到它们。唯一的断层发生在“网页渲染引擎(Blink)”将字形信息传递给“PDF 矢量打印引擎(Skia/PDF)”的那一瞬间。
在 macOS 环境下,由于系统字体的特殊存放机制和 Chromium 自身的沙盒策略,这种“网页能看但 PDF 无法打印”的诡异现象通常由以下三个深层原因导致。我们可以继续通过以下步骤抓出真正的元凶:
元凶排查一:macOS 的“字体册”激活状态与权限冲突
现代 macOS 为了节省空间,许多系统自带的中文字体(如某些特定字重的黑体、楷体,甚至部分 苹方的衍生字形)在默认情况下是“云端字体”。网页浏览器在普通模式下可以调用系统高级 API 动态渲染它们,但是 Headless Chromium (无头模式) 或 PDF 打印沙盒是一个受限的独立进程,它没有权限去触发 macOS 的云端字体下载或动态激活。
排查与修复方法:
― Google Gemini, Marp PDF 导出中文缺失解决
- 打开 Mac 自带的 字体册 (Font Book) 应用程序。
- 搜索 PingFang(苹方)或 Heiti(黑体)。
- 检查它们是否呈现灰色,或者右上角有没有一个“下载”的小云图标。如果有,请务必点击下载并全部激活。
- 如果已经激活,选中字体,右键选择 “验证字体” (Validate Font),确保没有出现警告或破损。
遵循 Gemini 老师的指引,我打开了字体册应用程序,结果:

真被 Gemini 老师说中了,PingFang 系列字体并没有被激活。在下载并激活之后:

问题解决!
3. 总结
这个问题的表象在于「Marp 在 macOS 下导出 PDF 文件时中文字符缺失」,其根本原因在于「macOS 的字体册可能出于某些原因没有激活系统内置的中文字体」,问题的迷惑性在于「即使 macOS 没有在本地激活这些字体,Chrome 等浏览器仍然可以正常渲染中文字符」,只有当尝试将 HTML 页面打印成 PDF 文件时,这个问题才会显现出来。
- 简单的解决办法:在字体册中找到 PingFang SC 或者其他需要的字体,点击「下载」并「激活」。
- 进一步的解决办法:考虑到 Marp 本身是基于 HTML 的技术,可以在其中插入在线字体(特别是 woff2 字体),这样可以确保在不同系统和平台上得到接近完全一致的渲染效果。