Pandoc Lua过滤器:将图像标题移到文档末尾

3

我对Lua pandoc过滤器完全不了解,所以这个问题超出了我的水平。

从一个Markdown文档开始,我想收集手稿中的所有图片,删除Latex调用以显示它们,并捕获它们的标题并在结尾处以块的形式显示它们,称为“Figures”。

例如,在中间的.tex文件中呈现图像如下:

\begin{figure}
  \includegraphics[width=1\linewidth]{figure1} \caption{Figure 1. Caption.}\label{fig:figure1}
\end{figure}

我想删除上述区块,将标题提取出来,并将其移动到具有以下结构的(现有)图表部分:
\section*{Figures}
  \begin{figure}[h!]
    \caption{Figure 1. Caption.}
  \end{figure}

  \begin{figure}[h!]
    \caption{Figure 2. Caption.}
  \end{figure}

我想强调在最终文档中不再显示数字。我发送的 .tex 文件需要遵循期刊的要求,将图片分开加载并在手稿中仅保留对它们的引用。

我尝试了一些 Lua 编码但没有成功。然后我发现 lua 完全没有看到我的图片。

我把这个放到了 .md 文件中:

\begin{figure}
  \includegraphics[width=1\linewidth]{figure1} \caption{Figure 1. Caption.}\label{fig:figure1}
\end{figure}

然后尝试使用以下方式检查Lua所看到的内容:

function Para (el) print(pandoc.utils.stringify(el)) end

但是没有任何关于图片的参考信息被打印出来(其他元素已经被打印出来,作为一个测试)。我尝试将Para替换为Str、Inline、Image、Pandoc,但是都没有成功。

所以我甚至无法在AST中捕获到这个图像...


我刚刚注意到我的lua过滤器只能看到中间的.md文件,而不能看到在转换成pdf之前的.tex文件...这里又出现了另一个问题... - Bakaburg
1
你能说一下如何创建中间的文本文件吗?这些图像的输入是什么样子的? - tarleb
1
是的,抱歉,我试图简化问题。图片要么在.Rmd文件中加载,要么由R生成。我上面写的LaTeX代码是在将其转换为PDF之前在.tex文件中表示图形的方式。 - Bakaburg
啊,那很有道理,谢谢!R Markdown 需要处理一些复杂的事情,因为 pandoc 的图片处理仍然非常基础。它 可能 在传递到 pandoc 时都是原始的 LaTeX,但其中一些图像可能会被包装在 Para 中的单个 Image 元素中传递。 - tarleb
我也尝试使用自定义图像,它们被识别为RawBlock。 - Bakaburg
显示剩余2条评论
2个回答

3

不必真正移动图表,只需告诉 LaTeX 在最后显示标题:

\usepackage{figcaps}

谢谢,问题在于我不想再打印实际的数字了,只需要在\section*{Figures}之后添加它们的标题,以遵守我发送.tex文件到期刊的模板规则。他们希望将图像作为外部文件,并在主.tex中引用它们(我应该在问题中提到这一点)。 - Bakaburg
@Bakaburg 啊,我想我明白了。我们可以暂时重新定义\includegraphics,让我测试一下... - samcarter_is_at_topanswers.xyz
@Bakaburg 实际上有一个专门的程序包可以做到这一点。请查看我编辑过的答案。 - samcarter_is_at_topanswers.xyz
谢谢!但问题仍然是我发送给他们的是 .tex 文件,而不是 pdf。所以我需要遵守他们的模板结构!我可以手动完成这个过程,但我希望有一个通用解决方案(也为了学习)。 - Bakaburg

2

将原始的LaTeX代码放入R Markdown输入中的问题在于它不会被pandoc处理,而是按原样传递。这可能非常有用,但在这种情况下,它限制了Lua过滤器的实用性。然而,在pandoc中,\begin{figure}...\end{figure}代码变成了“原始块”,仍然可以通过RawBlock从Lua过滤器中访问。您可以使用类似以下代码收集标题:

local captions = pandoc.List()

function RawBlock (raw)
  local caption = raw.text:match('\\caption%{(.*)%}')
  if caption then
    captions:insert(caption)
  end
end

function Pandoc (doc)
  -- append collected captions at the end
  doc.blocks:insert(captions:map(function(x) return pandoc.Para(x) end))
  return doc
end

或者将所有数字放入元数据字段中:
function Pandoc (doc)
  doc.meta.figures = captions:map(function (c)
      return pandoc.RawBlock('latex', c)
  end)
  return doc
end

1
谢谢!我已经接近成功了,但是你的代码更加简洁!我现在专注于通过 Meta 传递来创建一个可以在模板中使用的变量。但是,仅仅使用 meta.figures = caption(目前我只尝试了一个图像)会在 .tex 文件中输出 \textbackslash caption\{Figure 1. Example caption\},这不会被 pdflatex 识别。我该如何将原始的 LaTeX 代码通过 meta 传递到模板中? - Bakaburg
您可以将标题标记为原始TeX,如下所示:meta.figures = pandoc.RawBlock('latex', caption)。我相信这样做就可以了。 - tarleb
我收到了错误消息:"无法获取Pandoc值:无法获取元值:无法读取键值对的值:无法获取MetaValue:未知的元标记:RawBlock"。让我清理代码并将其发布在问题中。 - Bakaburg
啊,对了,那只适用于新的 pandoc 版本。尝试用 {...} 包装该值,就像 meta.figures = {pandoc.RawBlock(...)} 一样。 - tarleb
1
我已经更新了我的答案,包括基于元数据的解决方案的代码。请注意,我的代码的第一行在链接的gist中缺失。 - tarleb
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接