用 Pandoc + XeLaTeX —— Markdown 转为 PDF:踩坑全记录

1575 字
8 分钟
用 Pandoc + XeLaTeX —— Markdown 转为 PDF:踩坑全记录

作者:昇哥 & 易师 日期:2026-02-28 标签:Pandoc XeLaTeX 中文排版 macOS 隐私安全


一、为什么要折腾这套方案?#

市面上能把 Markdown 转成 PDF 的工具多如牛毛:Typora、语雀、Notion、印象笔记…… 那为什么不直接用,非要自己折腾一套命令行方案?

答案只有两个字:隐私。

这篇文档的内容是个人思想体系的核心整理,包含大量私密的思考与沉淀。 任何”上传到某个服务器再导出”的方案,都意味着你的内容经过了别人的服务器, 存在被存储、被分析、甚至被泄露的风险。

本地方案的原则:

  • 📴 全程离线,不经过任何第三方服务器
  • 🔒 文件只在自己的机器上处理
  • 🛠️ 完全可控,格式、字体、排版随心定制

这就是为什么我们选择了 Pandoc + XeLaTeX 这套纯本地的开源方案。


二、工具链介绍#

工具作用
Pandoc万能文档转换器,将 Markdown 转为 LaTeX 中间格式
XeLaTeX支持 Unicode 和中文的现代 LaTeX 引擎
xeCJKLaTeX 中文排版宏包,处理中文字体与断行
Apple SymbolsmacOS 内置字体,包含八卦等特殊 Unicode 符号字形

三、安装步骤#

3.1 安装 Pandoc#

macOS 上推荐用 Homebrew 安装:

Terminal window
brew install pandoc

验证安装成功:

Terminal window
pandoc --version

3.2 安装 XeLaTeX(MacTeX)#

XeLaTeX 包含在 MacTeX 发行版中。由于体积较大(约 4GB),建议安装精简版 BasicTeX:

Terminal window
brew install --cask basictex

安装完成后,刷新环境变量:

Terminal window
eval "$(/usr/libexec/path_helper)"

验证安装:

Terminal window
xelatex --version

3.3 安装必要的 LaTeX 宏包#

BasicTeX 不含所有宏包,需要手动补充:

Terminal window
sudo tlmgr update --self
sudo tlmgr install xecjk collection-fontsrecommended

四、第一次尝试:只用 Pandoc,失败了#

安装好 Pandoc 后,第一反应是直接用最简单的命令转换:

Terminal window
pandoc 《Dao核心理论》.md -o dao.pdf

结果:失败。 报错信息大意是找不到合适的 PDF 引擎。

于是指定引擎:

Terminal window
pandoc 《Dao核心理论》.md -o dao.pdf --pdf-engine=xelatex

这次生成了 PDF,但打开一看——问题一大堆

  1. 中文正常显示,但数学公式里的中文全部消失
  2. 八卦符号(☵☴☳☶☷☱☲☰)全部变成空方块
  3. 排版比较粗糙,页边距过大

光靠一行命令是不够的,需要一个专门的 LaTeX 配置文件来处理这些问题。


五、踩坑记录与解决过程#

坑一:数学公式中的中文丢失#

现象: 编译后 PDF 中,数学公式里的中文字符全部消失,只剩下英文和符号。

% 期望显示:
$$Dao = Fn_{现代思维解读}(...)$$
% 实际显示:
$$Dao = Fn_{}(...)$$ ← 中文消失了

原因: xeCJK 宏包默认不介入数学环境,数学模式下的 CJK 字符会被直接忽略。

解决方案: 创建 dao-header.tex 配置文件,加入以下设置:

\usepackage{xeCJK}
\xeCJKsetup{CJKmath=true} ← 这一行是关键

CJKmath=true 告诉 xeCJK:数学环境里的中文也要正常渲染。加上这行后,公式中的中文全部恢复正常。


坑二:八卦符号显示为方块(□□)#

现象: 文档中精心挑选的八卦符号 ☵☴☳☶☷☱☲☰,在 PDF 里全部变成了难看的空方块。

原因: 主字体宋体(Songti SC)的字形库里根本没有这些 Unicode 符号(U+2630U+2637), XeLaTeX 找不到字形,只好用方块占位。

排查过程:

先确认系统里有没有包含这些字符的字体:

Terminal window
fc-list | grep -i "apple symbols"
# → /System/Library/Fonts/Apple Symbols.ttf: Apple Symbols:style=Regular

再确认字符本身没问题(是字体问题,不是编码问题):

Terminal window
python3 -c "print('☵☴☳☶☷☱☲☰')"
# → ☵☴☳☶☷☱☲☰ ✅ 终端正常显示

结论: macOS 内置的 Apple Symbols 字体包含这些字符,只需要让 XeLaTeX 在遇到这些字符时自动切换字体即可。

解决方案: 使用 XeTeX 的 interchar 机制,为 U+2630U+2637 范围自动切换字体:

\newfontfamily\AppleSymbols{Apple Symbols}
\XeTeXinterchartokenstate=1
\newXeTeXintercharclass\SymClass
\XeTeXcharclass"2630=\SymClass
\XeTeXcharclass"2631=\SymClass
\XeTeXcharclass"2632=\SymClass
\XeTeXcharclass"2633=\SymClass
\XeTeXcharclass"2634=\SymClass
\XeTeXcharclass"2635=\SymClass
\XeTeXcharclass"2636=\SymClass
\XeTeXcharclass"2637=\SymClass
\XeTeXinterchartoks 0 \SymClass = {\begingroup\AppleSymbols}
\XeTeXinterchartoks \SymClass 0 = {\endgroup}

这段配置的意思是:凡是遇到 U+2630U+2637 范围内的字符,自动用 Apple Symbols 字体渲染,渲染完再切回主字体。


坑三:\sym 未定义报错#

现象: 加上字体配置后重新编译,又报了新错误:

! Undefined control sequence.
<argument> 上坎下巽,水风井(\sym
{☵☴})
l.1116 易师的基因,是一个卦象:\textbf{上坎下巽,水风井(\sym{☵☴})}

原因: .md 文件里有些地方用了 \sym{☵☴} 这个自定义命令来手动指定符号字体, 但 dao-header.tex 里只配置了字体,忘记定义 \sym 命令本身。

解决方案: 在配置文件中补充一行命令定义:

\newcommand{\sym}[1]{{\AppleSymbols #1}}

这样 \sym{☵☴} 就等价于 {\AppleSymbols ☵☴},用 Apple Symbols 字体渲染符号。


六、最终完整方案#

dao-header.tex#

\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{xeCJK}
\usepackage{fontspec}
% 中文字体设置
\setCJKmainfont{Songti SC}
\setCJKsansfont{PingFang SC}
\setCJKmonofont{Heiti SC}
% 允许数学环境中使用中文
\xeCJKsetup{CJKmath=true}
% 八卦符号字体
\newfontfamily\AppleSymbols{Apple Symbols}
% 定义 \sym 命令,用于在正文中手动指定符号字体
\newcommand{\sym}[1]{{\AppleSymbols #1}}
% 自动让八卦符号 U+2630–U+2637 走 Apple Symbols 字体
\XeTeXinterchartokenstate=1
\newXeTeXintercharclass\SymClass
\XeTeXcharclass"2630=\SymClass
\XeTeXcharclass"2631=\SymClass
\XeTeXcharclass"2632=\SymClass
\XeTeXcharclass"2633=\SymClass
\XeTeXcharclass"2634=\SymClass
\XeTeXcharclass"2635=\SymClass
\XeTeXcharclass"2636=\SymClass
\XeTeXcharclass"2637=\SymClass
\XeTeXinterchartoks 0 \SymClass = {\begingroup\AppleSymbols}
\XeTeXinterchartoks \SymClass 0 = {\endgroup}

Pandoc 转换命令#

Terminal window
pandoc 《Dao核心理论》.md -o dao.pdf \
--pdf-engine=xelatex \
-V mainfont="Songti SC" \
-V CJKmainfont="Songti SC" \
-H ~/dao-header.tex \
-V geometry:margin=2.5cm

运行后,PDF 顺利生成,中文、公式、八卦符号全部正确渲染 ✅


七、经验总结#

场景解决方案
中文在数学公式中丢失\xeCJKsetup{CJKmath=true}
特殊 Unicode 符号显示方块XeTeXinterchar 机制 + 备用字体
自定义 LaTeX 命令未定义在 header 文件中用 \newcommand 定义
验证字体是否包含某字符fc-list + python3 -c "print(...)"

💡 核心思路: XeLaTeX 的字体回退机制不是自动的,需要手动为特定 Unicode 范围指定备用字体。 遇到方块问题,第一步永远是先确认字体是否包含该字符,再考虑如何切换字体。


八、写在最后#

这套方案看起来比点几下按钮麻烦多了,但它换来的是:

  • 你的文字,只在你的机器上流动
  • 没有账号,没有云端,没有第三方
  • 一次配置,永久可用

对于承载个人核心思想的文档来说,这点折腾,值得。


参考资料#

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

用 Pandoc + XeLaTeX —— Markdown 转为 PDF:踩坑全记录
https://blog.fridolph.top/posts/2026-02-28__pandoc/
作者
Fridolph
发布于
2026-02-28
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
Fridolph
热爱 Coding、音乐和羽毛球的 90 后全栈工程师
公告
欢迎访问我的小站 ^_^ 我是昇哥,热爱Coding,喜爱音乐、羽毛球和摄影的 90后全栈工程师
分类
标签

文章目录