十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用CSS排版Markdown:从书稿到印刷级PDF的完整工作流

用CSS排版Markdown:从书稿到印刷级PDF的完整工作流 写 Markdown 的时候我从来没觉得排版是问题直到有一次我把一份十几万字的书稿丢给工具导 PDF出来的文件像一份“带标题的纯文本打印稿”——没有目录页码页眉像贴上去的代码一断页就血肉模糊。那一刻我意识到Markdown 擅长的是“写”它压根不管“排”。后来我花了几周时间折腾出一条把 Markdown 排成一本真正书籍的完整工作流这就是 Folio。它不是编辑器也不是现成的转换器而是一套“md 书稿 → 印刷级 PDF”的排版方案核心思路是继续用 Markdown 写让 CSS 干排版的活。这篇文章我会把整个链路、关键 CSS 参数、遇到的坑和现在日常使用的方式全部摊开讲适合那些写文档写到一定规模、开始追求出版质感的人。1. 为什么非要把 Markdown “排成书”写稿的人最懂这种痛先说清楚 Folio 想解决什么问题。我见过太多人用 Markdown 写博客、写 README 都很顺手可真到了要交付一份技术手册、课程讲义甚至一本小册子的时候就抓瞎了。Markdown 本身只负责结构标题是标题、段落是段落、代码是代码它不管这页留白多少、这行会不会孤零零掉到下一页。而这些恰恰是“书”和“文档”的分界线。1.1 我试过的三条弯路每一条都值得说最早我用的是 Pandoc 加 LaTeX 模板。Pandoc 从 Markdown 转 LaTeX 再出 PDF这条路非常强大但也很折磨人。LaTeX 对中文支持要配置 xelatex 和 ctex 宏包字体、章节格式、页眉页脚全部要用另一套语言改模板一行 CSS 都不认识。我只想调整一下标题字号就得去翻.cls 文件改完还得在终端里等半分钟编译。这种学习曲线对“以写作为主、不想整天跟模板搏斗”的人完全是负担。然后我试过 Typora 直接导出 PDF。Typora 作为 Markdown 编辑器确实舒服所见即所得导出 PDF 的效果也比普通转换器好。但它解决的只是“从编辑器到 PDF”这一步真正排版层面的控制力很弱目录页码要靠第三方插件封面和版本页没法优雅定制代码块在跨页时经常把上一页露半行奇偶页页眉也没法做“左页书名右页章节名”这种书刊规范。用来出差评报告行用来做书不行。市面上还有很多在线转换工具把 Markdown 粘进去就能出 PDF。这类工具适合应急不适合做书。它们对图片路径、公式渲染、字体嵌入的处理很不稳定经常出现“本机预览正常、发给别人就乱码”的问题。更致命的是没有命令行接口没法接入自动化构建流程。1.2 Folio 给自己定的三条规矩经过了上面这些折腾我给这个项目定了几条非常明确的原则。第一稿件格式必须是纯 Markdown不许为排版发明新的书写语法。写书的人只需要会最常用的那些语法标题、段落、列表、表格、代码块、图片、公式。排版的事全部交给模板。第二版面效果必须能精细控制因为“像书”和“是书”之间的差距全在细节里。页码放版心下面居中是文档放天头外侧靠近切口才是书标题左边顶格是网页首行缩进两字两端对齐才是书。这些细节用 CSS 逐个抠能做到像素级可控。第三构建流程必须可重复、可自动化、可以通过命令行一键执行。稿子改一个词重新执行一次构建命令就能得到新的 PDF而不是打开编辑器手动导出。围绕这三条 Folio 的定位变成一套“Markdown 编写 HTML 中间层 CSS 分页媒体渲染”的开源排版工作流。下面就是它的完整实现。2. Folio 的转换链路一个 md 文件是怎么一步步变成 PDF 的Folio 的全套管线用一句话概括就是Markdown 先转成语义化的 HTML再用 CSS 分页媒体引擎渲染成 PDF。这个过程分四步清洗、切章、渲染、装配。2.1 为什么选 HTML 加 CSS 分页媒体而不是 LaTeX核心原因是“用最低的学习成本拿到最强的版面控制力”。写网页的人对 CSS 已经很熟即使不熟CSS 也比 LaTeX 模板好懂得多。现代浏览器和渲染引擎支持一套叫 CSS Paged Media 的分页媒体规范它把网页的盒模型扩展到了多页场景可以用 page 规则控制纸张大小和页边距可以用 string-set 捕捉章节标题塞进页眉可以用 target-counter 把目录里的条目和真实页码关联起来这些都是做书必需的底层能力。相比 LaTeX这套方案有肉眼可见的优势改动即时反馈CSS 文件的某个属性改一个值重新构建就是一份新样式的 PDF技术栈通用社区里和 CSS 排版相关的资料远比 LaTeX 模板多。LaTeX 在学术排版领域依然是王者但如果你做的是技术手册、小说、小册子、产品说明书这类内容HTML 加 CSS 这套组合拳效率更高。2.2 管线四步清洗、切章、渲染、装配具体到 Folio 的实现整个构建脚本大概处理这么几件事。第一步是清洗原始 Markdown。作者写稿时往往很随意Windows 换行符和 Unix 换行符混用段落中间有零散空格表格里有复制 Excel 带过来的隐藏制表符。清洗脚本要统一换行符去除行尾空格规范表格分隔符把手写的 HTML 标签清理干净。这一步最容易被忽略但它是后面所有步骤稳定性的基础。第二步是切章。Folio 规定一本书放在一个 manuscript 目录下每章是一个独立的 Markdown 文件文件名就是排序依据。构建脚本读取一个轻量级配置文件里面声明了书名、作者、章节目录顺序然后把各个文件按顺序读进来为每一章生成包含 chapter 类的 HTML 片段。切章的意义在于每一章可以独立做分页控制比如新章必须从奇数页开始。第三步是渲染。这一步把 Markdown 转成 HTML。我用的是 markdown-it 这个解析器并挂上了几个插件一个负责把数学公式从 $...$、$$...$$ 转成 KaTeX 的 HTML 输出一个负责代码高亮一个负责把相对图片路径改写为构建目录下的真实路径。转出来的 HTML 是干净的语义标签h1、h2、p、pre、table、figure一个 CSS 类都没加类和作用全部由后面那张样式表决定。第四步是装配。脚本把每一章的 HTML 拼接到一个完整的 HTML 模板里前面插入封面页、版权页、目录页然后把全套 print.css 以 link 标签方式引入。模板里还会注入文档元信息比如 title 标签用于 PDF 元数据meta 标签可以控制 PDF 书签层级。最终这个 HTML 文件交给渲染引擎输出 PDF。2.3 渲染引擎选型Prince 和 WeasyPrint 的实际差异这块是整个管线里最影响成品质量的一环。我实际对比了两款引擎Prince 和 WeasyPrint。Prince 是商业软件个人和非商业用途免费下载对 CSS 分页媒体规范的支持是目前最完整的。Paged.js 那些高级特性比如运行页眉 target-counter、leader 点线在 Prince 里都直接可用。WeasyPrint 是纯开源实现由 Python 驱动日常写作和简单书籍足够但某些高级特性支持不上比如复杂的 running header 需要绕路实现表格断页表头重复在部分版本上还会失效。我在 Folio 里把两款引擎都做成了可选后端默认推荐 Prince。不是说开源不行而是当你需要把排版抠到“每个细节都符合书籍规范”时Prince 能少折腾几个晚上。但有一点必须说清楚无论是 Prince 还是 WeasyPrint都用同样的 HTML 输入和 CSS 样式表所以前端那套知识是完全通用的换引擎不换写法。唯一要注意的是不同引擎对 CSS 属性的支持程度有差异我会在第五节专门讲踩过的坑。3. 真正像“书”的排版细节全在 CSS 里HTML 负责结构CSS 负责让它“像书”。这一节我拿出 Folio 里真正在用的核心参数一条条说明它们为什么存在。这些都是我在浏览器默认样式基础上一点点磨出来的。3.1 页面规格与中文版心做书先定纸张和版心。Folio 默认设置是 A5 开本也就是 148mm 乘 210mm这个尺寸对技术手册、小说、诗歌集都合适拿着不累打印成本也低。页面规则长这样page { size: 148mm 210mm; margin: 24mm 18mm 22mm 20mm; }这里的 margin 上下左右故意不一样。上下是 24mm 和 22mm左右是 20mm 内侧、18mm 外侧。为什么内侧要比外侧宽因为装订会吃掉一部分版面空间内边距不给够靠近书脊的文字就容易被夹进阴影里。单页文档不需要考虑这个问题书必须要。真正讲究的书还会区分左右页让奇数页和偶数页的边距镜像对称。Prince 和 WeasyPrint 都支持 page:left 和 page:right 规则page:left { margin: 24mm 18mm 22mm 20mm; } page:right { margin: 24mm 20mm 22mm 18mm; }这样翻开书左边页和右边页的版心在视觉上是居中的像摊开的书本而不是两页独立的文档。正文的中文排版参数我放在根元素上html { font-size: 10.5pt; } body { font-family: Source Han Serif SC, Noto Serif CJK SC, serif; line-height: 1.75; text-align: justify; text-justify: inter-ideograph; } p { margin: 0; text-indent: 2em; }正文用宋体类字体10.5pt 是传统书刊的五号字大小行高 1.75 比网页常用的 1.6 到 1.7 略松一点因为纸面阅读密度和屏幕不一样。段落之间不加垂直间距而是靠首行缩进两字来区分段落这也是中文书籍的标准排版方式。读者一眼就能看出这排的是书不是网页长文。3.2 标题、目录和页码的联动标题在书里不只是字号更大的文字它是整个文档的导航骨架。Folio 里每章只有一个 h1表示章标题h2 是节标题h3 是小节标题。章标题必须另起一页并且从右页开始h1 { string-set: chaptitle content(text); break-before: page; break-after: page; }string-set 这行非常重要它把 h1 的文本内容捕捉成一个字符串变量后面页眉要用它。加上 break-before: page 和 break-after: page确保每一章的标题独占一页且下一节内容从新页开始。如果你希望书籍更紧凑也可以把 break-after 去掉让章标题页之后正文直接开始。目录页是 Folio 里“由代码自动生成”的部分。构建脚本扫描所有 h1、h2 的文本和 id生成一段目录 HTML然后用这段 CSS 把条目和真实页码关联起来.toc a { text-decoration: none; color: inherit; } .toc a::after { content: leader(.) target-counter(attr(href), page); }target-counter 会去计算目录里每个链接指向的那个元素最终落在第几页然后把页码填进去。leader(.) 生成一长串点线把标题和页码连接起来这就是书里常见的点线目录样式。这个能力几乎只有分页媒体引擎才有浏览器里做不到也是我坚持用 Prince 做默认后端的原因之一。3.3 页眉页脚的奇偶页处理页眉是书和文档的另一条分界线。Folio 采用传统书籍的页眉方案左右页眉不一样偶数页放书名奇数页放当前章节名页码放在页脚外侧。相关 CSS 长这样page:left { top-center { content: string(booktitle); font-size: 8pt; color: #666; } bottom-right { content: counter(page); font-size: 9pt; } } page:right { top-center { content: string(chaptitle); font-size: 8pt; color: #666; } bottom-left { content: counter(page); font-size: 9pt; } }这里 string(booktitle) 是在模板里预设的静态字符串string(chaptitle) 用的就是上一节提到的 string-set 捕获的章节名。页码 counter(page) 会自动递增。页眉字号比正文小一号颜色用灰色而不是纯黑避免干扰阅读。这就是“书”和“普通打印文档”的差距普通文档的页眉是重复的文档名书的页眉会跟着章节变化。3.4 断页、孤行寡行的强制约束这一段是排版细节里最“硬核”的也是普通 Markdown 转换器最不愿意处理的部分。做书必须控制好哪些元素不能跨页断开哪些元素之间不能断开。Folio 的核心约束如下h2, h3 { break-after: avoid; } h2, h3 { break-before: auto; } p { orphans: 2; widows: 2; } pre, table, figure, blockquote { break-inside: avoid; } table { break-inside: auto; }逐条解释。break-after: avoid 的意思是标题后面至少要跟着一行正文如果标题恰好落在页面最底部后面没有正文空间那就把标题一起推到下一页避免出现“标题孤零零悬在页脚”的情况。orphans 和 widows 控制段落的孤儿行和寡行orphans 是段落被断到下一页时留在上一页的最少行数widows 是段落被断页时留在当前页底部的最后一行至少要有几行。设为 2 的话就不会出现一页底部只有一行文字的情况。表格和代码块尽量整体搬动到下一页不拆得七零八落。但如果表格特别长一行都放不下有时候必须允许它跨页否则前面会空出大块白。这些约束在浏览器里不痛不痒在分页媒体里却是是否“专业”的关键区分点。4. 表格、代码、公式和图片Markdown 里的四个老大难Markdown 最大的优点是把内容约束在语义层面但表格、代码、公式、图片这四样东西会狠狠考验排版方案。Folio 对这个问题的处理是我觉得最值得拿出来分享的部分。4.1 表格别让宽表毁掉版面Markdown 表格写起来很爽但排进书里经常会出问题。最典型的是表格列太多、内容太长超过版心宽度直接溢出页面。Folio 的思路是“先瘦身再固化”。瘦身环节发生在清洗阶段。我加了一个检测脚本扫描每张表格的列数和每列的最大字符数如果发现超过版心宽度上限就在构建时输出警告提醒作者考虑拆表、转列表或者精简列项。这个警告在命令行里是黄色高亮作为构建流程的一部分能第一时间约束内容。如果表格宽度合适但仍可能跨页就在 CSS 里固定它的断页行为table { width: 100%; border-collapse: collapse; font-size: 9pt; } thead { display: table-header-group; } tr { break-inside: avoid; } td, th { border-top: 0.5pt solid #ccc; border-bottom: 0.5pt solid #ccc; padding: 3pt 6pt; vertical-align: top; }thead 加 display: table-header-group 的作用是当表格跨页时表头会在下一页自动重复一遍。长表格跨页后读者仍能看到列名不至于对着两列数字发懵。tr 的 break-inside: avoid 保证同一行的记录不会被劈成两半。单元格边框用 0.5pt 细线比网页常见的 1px 在打印纸上更干净。另外如果你习惯在 Excel 里排好表格再贴进 MarkdownFolio 的清洗脚本允许直接粘贴制表符分隔的纯文本它会自动转成标准 Markdown 表格语法省去手动对齐的工作。4.2 代码块断行、缩进和高亮技术类书稿最头疼的就是代码。引用别人的代码还好说真正的难题是代码太长放不进一行或者代码块跨页时从中间断开下一行代码只剩个右括号对不上上下文。Folio 对代码采用双管齐下。一是在预处理阶段用 highlight.js 给代码做语义高亮生成带 span 的 HTML二是在 CSS 里对代码块做严格的断页控制pre { break-inside: avoid; font-family: JetBrains Mono, Source Code Pro, monospace; font-size: 8.5pt; line-height: 1.5; background: #f7f7f7; padding: 8pt 10pt; border-radius: 2pt; } code { font-family: inherit; }pre 的 break-inside: avoid 让代码块作为一个整体不被拆断如果当前页剩余空间不够整个块就移到下一页。这是一个简单粗暴但有效的策略适合大多数情况。短代码块效果好超长代码块确实会留下大块空白。所以我还加了一个“行内代码折叠”的工具函数处理超长行时优先在运算符和逗号位置插入断行机会并缩进续行而不是让代码溢出页面边界。实际项目中一份几百页的技术手册代码块的占比往往在三分之一以上。这个环节稳了整本书的质量就稳了一大半。4.3 数学公式KaTeX 与引擎的配合数学公式在 Markdown 里写作 $...$ 或 $$...$$但在 HTML 层面有两套渲染路线。MathJax 输出的是 SVG 或 HTML 加 CSSKaTeX 输出的是 HTML 加 CSS 加少量字体。Prince 内置的 MathML 支持并不完美所以我要求在预处理阶段直接把公式转成 KaTeX 的 HTML 输出这样 Prince 只需要渲染普通 HTML 和字体不需要懂 MathML。具体操作是在 markdown-it 挂上 katex 插件const md require(markdown-it)({ html: true, linkify: true, typographer: true }).use(require(markdown-it-katex), { throwOnError: false, output: html });这样源文件里写的质能方程 $E mc^2$ 是现代物理的基石。在构建出来的 HTML 里会变成带 KaTeX 类和内联样式的 spanCSS 里给这类元素设置字体不变色即可。实测下来KaTeX 的排版质量和 LaTeX 非常接近而渲染速度比 MathJax 快不少对构建体验很有帮助。需要注意 KaTeX 依赖的特定字体文件在 Prince 里要能被正确加载否则公式会显示为空白或回退字体建议把 KaTeX 的字体目录一并复制进构建目录。4.4 图片路径从相对路径到资源装配图片路径问题是最烦人的一个。作者写稿时用的是相对路径比如images/architecture.png但如果构建脚本在另一个目录运行或者图片放在子文件夹里路径就全对不上了。Folio 的清洗脚本会统一处理这个事它会读取出 Markdown 里所有的图片引用将相对路径解析后复制到构建目录下的 assets 文件夹然后把 Markdown 里的路径改写为 assets/ 下的新路径。这样即使原稿移动了图片文件只要 manuscript 目录整体迁移构建就不会断。CSS 层面我给图片设置了自适应版心的约束img { max-width: 100%; height: auto; break-inside: avoid; } figure { text-align: center; break-inside: avoid; } figcaption { font-size: 8.5pt; color: #666; margin-top: 4pt; }图片宽度最大不超过版心高度自动等比缩放。figure 和 figcaption 整体不允许跨页断开否则图注会孤零零跑到下一页读者对不上号。如果你有特别宽的图想横着放可以给 img 单独加一个 rotate 类用 CSS transform 旋转 90 度并调整页面方向这在 Folio 里也有现成模板不过我更建议直接把这种图拆出来放附录别打断正文阅读节奏。5. 踩坑复盘头两版样书里的真实事故Folio 不是一次写成的中间有两版样书排出来效果不堪入目。这一节我按真实排查顺序复盘几个典型事故这些坑可能会出现在任何想用 CSS 做书的人面前。5.1 目录页码对不上target-counter 不是万能的第一版样书的目录页一片混乱有的章节后面没有页码有的页码少了一页。我一开始以为是 markdown-it 生成的链接 id 有重复后来逐条检查发现问题出在 target-counter 的 attr(href) 解析上。Prince 里必须写成attr(href url)才能确保 href 被当作 URL 解析只写attr(href)在某些版本里会拿到一串原始字符串导致目标匹配失败。修正方式是把目录 CSS 改成.toc a::after { content: leader(.) target-counter(attr(href url), page); }另外还有一个隐蔽问题构建脚本生成的目录链接 href 是#chapter-1这样的片段但如果页面模板里有多个同名 id 的锚点Prince 会匹配第一个导致页码偏差。现在的构建脚本会在切章时为每个 h1、h2 生成带唯一序号的 id彻底杜绝同名冲突。5.2 中文标点悬挂浏览器默认行为与打印的矛盾做书的人都希望正文两端对齐时标点能悬挂在行尾这样右边不会出现难看的锯齿。浏览器和分页引擎对 Chinese 标点悬挂的支持都不太完整。Prince 提供了 text-hanging-punctuation 属性但实测它对中文全角引号、逗号、句号的支持并不稳定某些组合下会导致整行间距被拉得很开。我最终的妥协方案是不追求严格的标点悬挂而是通过两端对齐加合理的断行规则让标点尽量自然落在行尾。对于左右对齐后某些行间距特别大的情况我在清洗脚本里加了一个可选的“标点挤压”后处理把行尾是全角标点的行稍微压缩字距。这个后处理不是百分百保险但它让样书从“一眼看出是浏览器渲染”变成了“接近出版社的标准”。5.3 表格跨页后表头丢失display 属性的兼容性前面提到 thead 的 display: table-header-group 可以重复表头但这个属性在 WeasyPrint 的某些版本里失效。我实际遇到的情况是表格跨页后下一页直接出现数据行列名全部丢失。排查后确认是 WeasyPrint 对 table-header-group 的重复渲染支持不完整。如果你必须用 WeasyPrint 后端我的建议是尽量把表格列数控制在 3 到 4 列以内减少跨页概率或者干脆给大表加一个禁止跨页的类让它整体挪到下一页。Prince 在这块的兼容性就好很多所以我在 Folio 的配置文档里明确标注默认引擎用 Prince只有轻量文档才建议切 WeasyPrint。5.4 超链接变蓝变下划线打印样式要重置这套书稿里有很多交叉引用和外部链接第一版样书里它们全部变成浏览器经典的蓝色加下划线打印出来既脏又分散注意力。原因很简单Prince 基于 WebKit 内核链接默认样式没有被重置掉。修复方法是把所有链接在打印样式表里统一重置a { color: inherit; text-decoration: none; }保留链接的可点能力但剥掉视觉上的“网页感”。如果某些链接真的是需要读者访问的网址可以在排版时用 ::after 把 URL 以小字号打印出来作为脚注信息。这样既不破坏正文排版又保留了可追溯性。5.5 封面和版权页的“页面边界”问题最后还有一个容易忽视的坑封面页、版权页和正文页不应该有相同的页眉页脚。第一版样书里封面页居然也带上了页码和页眉看起来非常业余。解决方法是给封面和版权页的容器手动加一个 page 命名规则.cover { page: cover; } page cover { margin: 0; top-center { content: none; } bottom-center { content: none; } }原理是 CSS 分页媒体允许命名页面然后通过元素上的 page 属性把特定元素分配到那个页面上下文。封面页用无页眉页脚、无边距的独立页面规则正文再回到默认的书籍页规则。这个功能浏览器里没有但分页媒体引擎都支持是 Folio 成书质感的重要一环。6. 把 Folio 接进日常写作流水线工具做得再好如果接不进写作流程就会被闲置。Folio 落地的最后一公里是和编辑器、版本管理、持续构建的整合。6.1 VS Code 里保存即编译写作时最舒服的姿势是改完一个字保存PDF 自动更新。我用 VS Code 的 Tasks 功能接入 Folio。在 .vscode/tasks.json 里定义一个监听任务{ version: 2.0.0, tasks: [ { label: folio build, type: shell, command: folio build, group: build, problemMatcher: [] }, { label: folio watch, type: shell, command: folio watch, group: { kind: build, isDefault: true }, problemMatcher: [] } ] }folio watch 会监听 manuscript 目录下的所有 .md 文件文件一变就重新构建。配合 VS Code 的 PDF 预览插件左边写 Markdown右边实时看排好的 PDF体验和 Typora 的所见即所得不一样但更接近“印刷厂原稿”的感觉。Prince 的可执行文件名是 prince安装时把它加进 PATHFolio 就能直接调用。如果你用 WeasyPrint 后端也可以把命令换成 python -m weasyprint不过效果差异在第五节已经说过了。6.2 与 Typora 等编辑器的互补使用有人问我Folio 会不会抢 Typora 的活恰恰相反两者是互补关系。Typora 是一个优秀的 Markdown 编辑器它的强项是“写”让你专心写内容实时看格式。Folio 的强项是“排”把写完的稿子变成一本像样的书。我的日常流程是在 Typora 里写作和初稿修改因为它的编辑体验最顺滑稿子定稿后回到 VS Code 跑 Folio 构建 PDF。Typora 也能导出 PDF但那是“文档级”的 PDFFolio 出的是“书籍级”的 PDF两者定位不同不冲突。如果你习惯在 VS Code 里用 Markdown 插件写作也是一样的逻辑。Folio 是一个构建层工具它不关心你用哪个编辑器写稿反正它只读取 manuscript 目录下的 .md 文件。6.3 配合 Git 做版本管理用 Git 管理书稿比管理代码还要有价值。Markdown 是纯文本Git 能精确看到每一个字的变化这对写长文档来说太关键了。我在 Folio 里把 manuscript 目录和 styles 目录纳入 Git 仓库build 目录放进 .gitignore因为 PDF 是生成产物不该进版本库。每次定稿一个章节就 commit 一次tag 一个版本号。等整本书完成时回看提交记录能清楚看到每一章的演化轨迹。6.4 还能往哪里扩展Folio 目前的输出是 PDF但中间的 HTML 中间层意味着它天然可以扩展出其他格式。Word 方向可以接 Pandoc 把 HTML 转成 docx适合需要交出版社做后续编辑的场景ePub 方向可以用同一套 HTML 源文件配合另一套 screen.css 输出电子书甚至可以直接把 HTML 中间层发到 WordPress 作为文章内容实现 Markdown 书稿到博客的无缝转换。我在 Folio 的脚本里预留了一个 export 参数后面可以按folio export --format epub的形式扩充插件。不过要泼一盆冷水不要指望一个命令解决所有格式的美观问题。ePub 的排版引擎和 PDF 完全不同Word 的排版逻辑更不一样。Folio 的价值不在于“一次转换处处完美”而在于“一份源稿多端可控”——你只需要维护内容每个输出端各有自己的模板这才是文档工程的正确姿势。根据我这段时间的实际体验Folio 最大的回报不是那个漂亮的 PDF而是让我重新敢写长文了。以前一想到要排版就犯懒现在只管写写完了跑一条命令剩下的交给 CSS。最后分享一个小技巧在打印样书之前先拿一小章节跑一遍构建把 CSS 里的断页、孤行问题全部调好再放开整本书。否则几百页的一次性构建如果版面出错修改后重新构建的等待时间会让人非常烦躁。排版这件事和写代码一样先让小规模跑通再上全量。
返回列表