PDFLang 是一门什么样的语言
PDFLang 是一门只做一件事的脚本语言:把「正确的 PDF 应该是什么样」写下来,让机器 拿文件去比对。
脚本的扩展名是 .pdfl,执行它的是 pdfl,一个用 Rust 写的命令行工具。
它要解决的问题
Section titled “它要解决的问题”总得有人判断一个 PDF 能不能付印、能不能归档、能不能发给客户。
这个判断背后的规则是具体的。油墨总量低于 300%。字体全部内嵌。每一页都有裁切框。 条码与旁边印着的号码一致。没有哪一页被误旋转。
这些规则通常同时存在于三个地方:做这行最久的那个人的脑子里、一份没人打开的检查 清单里,以及一个只有作者能维护的脚本里。然后那个人离职了,清单过时了,脚本变得 没人敢碰。
PDFLang 的存在,是为了让规则集中在一个文件里,而且懂这些规则的人自己就能读懂。
脚本长什么样
Section titled “脚本长什么样”profile "press-ready" {
check "油墨量在限值内" tags: ["prepress"] { require prepress::validate_tac_limits(300) }
check "字体已内嵌" { doc.fonts.each { |font| assert font.is_embedded, "字体 #{font.name} 没有内嵌" } }}四个词撑起了这门语言的大部分:
profile把一组 check 归拢起来并命名。check是一条规则,会成为报告中的一节。require在前置条件不成立时终止该 check。assert记录一条结果,带上你写的信息。
为什么它读起来是这样
Section titled “为什么它读起来是这样”没有类、没有继承、没有类型声明、没有分号。这是决定,不是遗漏:它设定的读者懂印前, 不懂编程。
同样的意图体现在更小的地方。页码从 1 开始,就像编译器之外的所有人那样数。尺寸可以
直接写 3mm 和 1in。百分比就写 300%。
它能检查什么
Section titled “它能检查什么”七个命名空间,每个对应一类工作:
text::— 提取、规范化、检索、各类校验、个人信息struct::— 对象、元数据、XMP、安全、哈希visual::— 分辨率、视觉比对、感知哈希、质量prepress::— 油墨量、分色、专色、字体、各类页面框codes::— 条码与二维码的检测、解码、校验fix::— 页面框、页面、水印、合并与拆分、优化data::— 来自文件之外的术语表、数据集和查找表
你会拿回什么
Section titled “你会拿回什么”一份报告。删减之后,一条失败的 check 是这样的:
{ "script_name": "prepress.pdfl", "input_file": "magazine.pdf", "status": "FAIL", "error_count": 2, "diagnostics": [ { "id": "PDFL-093751a2", "severity": "error", "check_name": "Ink coverage", "message": "page 7: 324% ink (limit 300%)" } ]}留意那个 message。它不是堆栈跟踪,而是一句可以直接转发给送来文件的供应商的话
——这正是这门语言要你亲手把它写在规则旁边的原因。
默认是 JSON。CSV、HTML 和 PDF 是给需要阅读报告而不是解析报告的人用的;当结果需要 出现在团队本来就会看的地方时,还有 SARIF 和 JUnit。
放进流水线里跑
Section titled “放进流水线里跑”pdfl run press-ready.pdfl magazine.pdf > report.json退出码承载了结论,因此 Shell 脚本或 CI 任务无需解析任何内容即可据此分支:
| 退出码 | 含义 |
|---|---|
0 |
全部通过 |
1 |
仅有警告 |
2 |
校验错误 |
3 |
脚本语法错误 |
10 |
文档根本读不了 |
工具说英文,你的脚本不必
Section titled “工具说英文,你的脚本不必”pdfl 自己打印的信息——诊断、错误、命令行帮助——是英文的,这是命令行工具的惯例。
本文档翻译成七种语言,但一条失败的 check 仍会报出 page 7: 324% ink (limit 300%)。
你自己脚本里的信息属于你。用读报告的人所说的语言去写。
语言手册是唯一值得从头读到尾的一章。它之后的内容都是参考: 每个命名空间一章、CLI 命令,以及围绕完整案例组织的 实用范例——印刷厂、法律出版社、实验室、CI 流水线。
如果你更愿意读代码而不是读文字,示例是保留了注释的可运行配置。