用于 pandoc(带有交叉引用)的 Lua 过滤器,提取表格的标签

问题描述 投票:0回答:2

我正在使用 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
lua latex pandoc
2个回答
1
投票

实际上,我认为如果我颠倒调用过滤器的顺序,那么此信息将包含在表格标题中:

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

0
投票

我们先来看看如何调试这个。 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 和其他过滤器之间运行该过滤器应该可以解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.