如何解决Pandoc转换含@preview库导入的Typst文档报错问题?
问题概述
Pandoc可将Typst文档转成Markdown,能正常识别#import "myfile.typ": a这类相对导入,但无法处理Typst Universe的#import "@preview/cetz:0.3.4": *格式库导入。我需要用基于Pandoc的showman工具,为引入了cetz库的新Typst包生成README。
复现步骤
- 仅包含相对导入的
test1.typ,可通过Pandoc正常转换为Markdown; - 加入
@preview/cetz:0.3.4导入的test2.typ,用Typst编译完全正常,但Pandoc转换时抛出错误:pandoc: @preview/cetz:0.3.4: withBinaryFile: does not exist (No such file or directory) - 手动下载cetz v0.3.4到本地
./@preview/cetz:0.3.4/目录后,报错变为:pandoc: @preview/cetz:0.3.4: withBinaryFile: inappropriate type (is a directory)
显然Pandoc误将库的目录路径当作单个文件尝试读取。
环境信息
- Pandoc版本:3.1.3
- Typst版本:0.13.1
可行解决方案
1. 直接修改导入路径为本地文件路径
把Typst源文件中的#import "@preview/cetz:0.3.4": *替换为指向本地cetz库主文件的相对路径,比如假设cetz的入口文件是cetz.typ,则改为:
#import "./@preview/cetz:0.3.4/cetz.typ": *
这样Pandoc就能正确识别具体文件,而非尝试读取整个目录。
2. 用Lua过滤器自动替换导入语句
编写Pandoc Lua过滤器,在转换前自动替换Universe库的导入路径为本地对应文件路径,避免手动修改源文件。示例过滤器代码(保存为fix-typst-imports.lua):
function CodeBlock(block) if block.classes[1] == "typst" then -- 替换cetz的Universe导入为本地路径 block.text = string.gsub(block.text, '#import "@preview/cetz:0.3.4": %*', '#import "./@preview/cetz:0.3.4/cetz.typ": *') return block end end -- 处理文档中的导入语句(如果是直接在文档内容里而非代码块) function RawBlock(format, text) if format == "typst" then text = string.gsub(text, '#import "@preview/cetz:0.3.4": %*', '#import "./@preview/cetz:0.3.4/cetz.typ": *') return RawBlock(format, text) end end
使用时执行命令:
pandoc test2.typ -o test2.md --lua-filter=fix-typst-imports.lua
3. 给showman工具加预处理脚本
如果需要批量处理或不想修改源文件,可以在调用showman前,用脚本先替换Typst文件中的Universe导入路径,完成README生成后再恢复原导入语句。比如用sed命令(Linux/macOS):
# 替换导入路径 sed -i.bak 's/#import "@preview\/cetz:0.3.4": \*/#import "\.\/@preview\/cetz:0.3.4\/cetz\.typ": \*/g' test2.typ # 调用showman生成README showman test2.typ -o README.md # 恢复原文件 mv test2.typ.bak test2.typ
内容的提问来源于stack exchange,提问作者falsePockets

