Pandoc与LaTeX:导入公式标签时Lua过滤器报错求助
问题
已知pandoc-eqnos过滤器无法正常工作且处于半废弃状态,因此编写Lua过滤器实现以下目标:提取LaTeX中的equation环境,生成仅包含公式及对应标签的独立文件,将公式转为图片后导入最终docx文件。运行时出现报错:
Error running filter filter.lua: Inline, list of Inlines, or string expected, got table
最小工作示例(MWE)
.tex文件代码
\documentclass{article} \usepackage{amsmath} \usepackage{mathtools} \usepackage{blindtext} \usepackage{tikz} \usepackage{pgfplots} \pgfplotsset{compat=newest} \usepackage{siunitx} \usepackage{graphicx} \usepackage{stix2} \usepackage{microtype} \usepackage{pifont} \title{Sections and Chapters} \author{Overleaf} \date{\today} \begin{document} \maketitle \tableofcontents \section{Introduction} This is the first section. \begin{equation} \underset{\mathrm{Einstein}}{E} = mc^2 \end{equation} Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam lobortis facilisis sem. Nullam nec mi et neque pharetra sollicitudin. Praesent imperdiet mi nec ante. Donec ullamcorper, felis non sodales commodo, lectus velit ultrices augue, a dignissim nibh lectus placerat pede. Vivamus nunc nunc, molestie ut, ultricies vel, semper in, velit. Ut porttitor. Praesent in sapien. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis fringilla tristique neque. Sed interdum libero ut metus. Pellentesque placerat. Nam rutrum augue a leo. Morbi sed elit sit amet ante lobortis sollicitudin. Praesent blandit blandit mauris. Praesent lectus tellus, aliquet aliquam, luctus a, egestas a, turpis. Mauris lacinia lorem sit amet ipsum. Nunc quis urna dictum turpis accumsan semper. \end{document}
Lua过滤器代码
local file = "C:/Logs/test.tex" function all_trim(s) return s:match("^%s*(.-)%s*$") end function file_exists(name) local f = io.open(name, "r") if f ~= nil then io.close(f) return true else return false end end function get_line(filename, line_number) local i = 0 for line in io.lines(filename) do i = i + 1 if i == line_number then return line end end return nil -- line not found end function lines_from(file) if not file_exists(file) then return {} end local lines = {} for line in io.lines(file) do lines[#lines + 1] = line end return lines end -- tests the functions above local lines = lines_from(file) local section,equation = 0, 0 for k, v in pairs(lines) do if string.find(v, "\\section") then figure = 0 section = section + 1 end if string.find(v, "\\begin{equation}") then equation = equation + 1 end end function Math(el) if (el.mathtype == "DisplayMath") then counter = counter + 1 io.output("C:/Logs/output.tex") io.write("\\documentclass[preview]{standalone}", "\n") local i = 2 for k, v in pairs(lines) do while not string.find(lines[i], "\\begin{document}") do io.write(lines[i], "\n") -- write preamble i = i + 1 end end io.write("\\begin{document}", "\n") io.write("\\begin{equation}", "\n") io.write(el.text, "\n") io.write("\\label{"..section.."."..equation.."}", "\n") io.write("\\end{equation}", "\n") io.write("\\end{document}", "\n") io.close() os.execute("cd C:/Logs & pdflatex output.tex & convert -density 288 output.pdf -alpha off output.png") return { pandoc.Para({pandoc.Image({},"C:/Logs/output.png")})} end end
执行命令
pandoc --from latex+raw_tex --filter pandoc-eqnos --lua-filter=filter.lua -s test.tex -o test.docx
错误信息
Error running filter filter.lua: Inline, list of Inlines, or string expected, got table
解决方案
错误原因
报错的直接原因是pandoc.Image构造参数不合法:pandoc.Image({},"C:/Logs/output.png")中第一个参数是空表,但Image要求第一个参数为Inline元素列表、单个Inline元素或字符串,空表不符合要求。
除此之外,原过滤器还有其他潜在问题:
counter变量未初始化,会触发运行时错误;- 导言区写入逻辑重复遍历原文件,导致代码冗余且可能重复写入内容;
- 全局计数变量
section和equation无法对应当前处理的公式,会导致所有公式使用相同标签。
修复步骤
- 给
pandoc.Image添加合法的替代文本,将空表替换为公式文本对应的Inline元素; - 初始化
counter等计数变量; - 预提取原文件的导言区,避免重复遍历;
- 调整计数逻辑,确保每个公式对应正确的章节和公式编号。
修改后的Lua过滤器代码
local input_file = "C:/Logs/test.tex" local output_dir = "C:/Logs/" function all_trim(s) return s:match("^%s*(.-)%s*$") end function file_exists(name) local f = io.open(name, "r") if f ~= nil then io.close(f) return true else return false end end function lines_from(file) if not file_exists(file) then return {} end local lines = {} for line in io.lines(file) do lines[#lines + 1] = line end return lines end -- 预加载原文件并提取导言区 local all_lines = lines_from(input_file) local preamble = {} local in_preamble = true for _, line in ipairs(all_lines) do if in_preamble then table.insert(preamble, line) if string.find(line, "\\begin{document}") then in_preamble = false end else break end end -- 初始化计数器 local current_section = 0 local equation_counter = 0 local global_counter = 0 -- 预统计章节数量 for _, line in ipairs(all_lines) do if string.find(line, "\\section") then current_section = current_section + 1 end end function Math(el) if el.mathtype == "DisplayMath" then global_counter = global_counter + 1 equation_counter = equation_counter + 1 -- 生成唯一文件名,避免覆盖 local tex_filename = output_dir .. "output_" .. global_counter .. ".tex" local pdf_filename = output_dir .. "output_" .. global_counter .. ".pdf" local png_filename = output_dir .. "output_" .. global_counter .. ".png" -- 写入独立TeX文件 local f = io.open(tex_filename, "w") f:write("\\documentclass[preview]{standalone}\n") -- 跳过原documentclass行,写入剩余导言区 for i = 2, #preamble do f:write(preamble[i] .. "\n") end f:write("\\begin{document}\n") f:write("\\begin{equation}\n") f:write(el.text .. "\n") f:write("\\label{" .. current_section .. "." .. equation_counter .. "}\n") f:write("\\end{equation}\n") f:write("\\end{document}\n") f:close() -- 编译并转换为图片,添加nonstopmode避免中断 os.execute("cd " .. output_dir .. " & pdflatex -interaction=nonstopmode " .. tex_filename) os.execute("convert -density 288 " .. pdf_filename .. " -alpha off " .. png_filename) -- 返回合法的Image元素,用公式文本作为替代文本 return pandoc.Para({ pandoc.Image({pandoc.Str(el.text)}, png_filename) }) end end
执行说明
修改后执行原命令即可,生成的每个公式会对应独立的output_*.tex、output_*.pdf和output_*.png文件,避免文件覆盖,同时公式标签能正确关联章节编号。
内容的提问来源于stack exchange,提问作者user3204810
相关产品推荐
相关产品推荐

