我正在使用 pandoc (带有 pandoc-crossref 过滤器)将 markdown 文档转换为 LATEX。但我希望表作为常规(浮动)表环境输出,而不是作为(非浮动)长表输出。我编写了一个 Lua 过滤器来执行此操作,它是成功的,只是它无法提取有关表的 pandoc-crossref 标签的信息。我需要提取此信息,以便可以将此标签作为 LATEX 输出的一部分包含在内(从而交叉引用该表)。这是一个最小的例子。
首先,这是一个最小的 Markdown 文档 (input.md),其中仅包含一个带有标签 tbl:table1 的表格(可以通过 pandoc-crossref 读取):
| First Header | Second Header |
|:-------------|:--------------|
| Content Cell | Content Cell |
| Content Cell | Content Cell |
: Table example {#tbl:table1}
其次,这是我的最小 Lua 过滤器 (table.lua),它尝试从此 Markdown 文档中提取此标签 (tbl:table1):
function Table(elem)
local id = elem.attr.identifier or ''
if id ~= '' then
print("Table label: " .. id)
else
print("Table does not have a label")
end
end
return {
{ Table = Table }
}
第三,当我从命令提示符运行 pandoc 时,我希望这个 Lua 过滤器在命令提示符窗口中打印“Table label: tbl:table1”,但它却打印“Table does not have a label”。这是我在命令提示符中的命令行:
pandoc input.md --output=output.tex --from markdown+pipe_tables --to latex --filter pandoc-crossref --lua-filter=table.lua
非常感谢任何帮助!
顺便说一句,这是我更广泛的 Lua 过滤器,它(几乎成功)输出一个表而不是长表:
function Table(tbl)
local simpleTable = pandoc.utils.to_simple_table(tbl)
local blocks = pandoc.Blocks{}
-- Function to create a LaTeX row
local function create_latex_row(cells)
local latex_row = ""
for i, cell in ipairs(cells) do
for _, content in ipairs(cell) do
latex_row = latex_row .. pandoc.write(pandoc.Pandoc({content}), "latex")
end
if i < #cells then
latex_row = latex_row .. " & "
end
end
return latex_row .. " \\\\"
end
-- Determine the number of columns (using header or first row)
local num_cols = 0
if simpleTable.header and #simpleTable.header > 0 then
num_cols = #simpleTable.header
elseif #simpleTable.rows > 0 then
num_cols = #simpleTable.rows[1]
end
-- Assume all columns are left-aligned for simplicity
local col_alignment = string.rep("l", num_cols)
-- Begin table environment
blocks:insert(pandoc.RawBlock("latex", "\\begin{table}[tbp]"))
-- Add caption
if tbl.caption then
local caption_text = pandoc.utils.stringify(tbl.caption)
blocks:insert(pandoc.RawBlock("latex", "\\caption{" .. caption_text .. "}"))
end
-- Add label using tbl.attr.identifier
-- This is the part that doesn't work
if tbl.attr and tbl.attr.identifier and tbl.attr.identifier ~= "" then
blocks:insert(pandoc.RawBlock("latex", "\\label{" .. tbl.attr.identifier .. "}"))
end
blocks:insert(pandoc.RawBlock("latex", "\\centering"))
blocks:insert(pandoc.RawBlock("latex", "\\begin{tabular}{" .. col_alignment .. "}"))
-- Process header
if simpleTable.header and #simpleTable.header > 0 then
local header_row = create_latex_row(simpleTable.header)
blocks:insert(pandoc.RawBlock("latex", header_row))
end
-- Process rows
for _, row in ipairs(simpleTable.rows) do
local latex_row = create_latex_row(row)
blocks:insert(pandoc.RawBlock("latex", latex_row))
end
-- End tabular and table environment
blocks:insert(pandoc.RawBlock("latex", "\\end{tabular}"))
blocks:insert(pandoc.RawBlock("latex", "\\end{table}"))
return blocks
end
实际上,我认为如果我颠倒调用过滤器的顺序,那么此信息将包含在表格标题中:
pandoc input.md --output=output.tex --from markdown+pipe_tables --to latex --lua-filter=table.lua --filter pandoc-crossref
所以我现在可以运行以下 table.lua 过滤器,这解决了我的问题:
function Table(tbl)
local simpleTable = pandoc.utils.to_simple_table(tbl)
local blocks = pandoc.Blocks{}
-- Function to create a LaTeX row
local function create_latex_row(cells)
local latex_row = ""
for i, cell in ipairs(cells) do
for _, content in ipairs(cell) do
latex_row = latex_row .. pandoc.write(pandoc.Pandoc({content}), "latex")
end
if i < #cells then
latex_row = latex_row .. " & "
end
end
return latex_row .. " \\\\"
end
-- Determine the number of columns (using header or first row)
local num_cols = 0
if simpleTable.header and #simpleTable.header > 0 then
num_cols = #simpleTable.header
elseif #simpleTable.rows > 0 then
num_cols = #simpleTable.rows[1]
end
-- Assume all columns are left-aligned for simplicity
local col_alignment = string.rep("l", num_cols)
-- Begin table environment
blocks:insert(pandoc.RawBlock("latex", "\\begin{table}[tbp]"))
blocks:insert(pandoc.RawBlock("latex", "\\centering"))
-- Process caption and label
if tbl.caption and #tbl.caption.long > 0 then
local caption_str = pandoc.utils.stringify(tbl.caption.long)
local caption_text, label = caption_str:match("^(.*) {#(.-)}$")
if caption_text and label then
blocks:insert(pandoc.RawBlock("latex", "\\caption{" .. caption_text .. "}"))
blocks:insert(pandoc.RawBlock("latex", "\\label{" .. label .. "}"))
else
blocks:insert(pandoc.RawBlock("latex", "\\caption{" .. caption_str .. "}"))
end
end
blocks:insert(pandoc.RawBlock("latex", "\\begin{tabular}{" .. col_alignment .. "}"))
-- Process header
if simpleTable.header and #simpleTable.header > 0 then
local header_row = create_latex_row(simpleTable.header)
blocks:insert(pandoc.RawBlock("latex", header_row))
blocks:insert(pandoc.RawBlock("latex", "\\hline")) -- Optional: Adds a horizontal line after the header
end
-- Process rows
for _, row in ipairs(simpleTable.rows) do
local latex_row = create_latex_row(row)
blocks:insert(pandoc.RawBlock("latex", latex_row))
end
-- End tabular and table environment
blocks:insert(pandoc.RawBlock("latex", "\\end{tabular}"))
blocks:insert(pandoc.RawBlock("latex", "\\end{table}"))
return blocks
end
我们先来看看如何调试这个。 Pandoc 允许使用 --to=native
打印
内部文档表示。这对于了解正在发生的事情非常有用。当我在你的桌子上运行
pandoc --filter=pandoc-crossref --to=native
时,我得到的是:
[ Div
( "tbl:table1" , [] , [] )
[ Table
( "" , [] , [] )
-- ...
]
]
这给了我们需要的提示:pandoc-crossref 将表放置在
Div
元素中并在其中添加 id! (也可以使用 pandoc/logging 帮助程序在 Lua 脚本中进行此类检查。)
要改变这一点,我们可以使用额外的过滤器(或将其包含在您的其他过滤器中):
function Div (div)
-- Check if the div contains just a single table
if #div.content == 1 and div.content[1].t == 'Table' then
-- move the id to the table, and unwrap the table.
local tbl = div.content[1]
tbl.identifier = div.identifier
return tbl
end
end
在 pandoc-crossref 和其他过滤器之间运行该过滤器应该可以解决问题。