Pandoc LaTeX 图片环境转换指南:figure 与 subfigure 到 HTML5 的完整链路
2026/9/20 6:00:50 网站建设 项目流程

Pandoc LaTeX 图片环境转换指南:figure 与 subfigure 到 HTML5 的完整链路

【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc

导读

本文以仓库中的命令测试用例 test/command/3577.md 为主体,深入讲解 Pandoc 如何将 LaTeX 的figuresubfigure图片环境(含\caption\label[ht]等放置参数)转换为 HTML5 的嵌套<figure>/<figcaption>结构,并给出可复现的命令、逐行输出解析与底层源码原理。读完本文,你将掌握 LaTeX 文档中的单图、子图(subfloat)场景迁移到 HTML5 时的完整行为,以及如何利用data-latex-placement属性做进一步的页面布局控制。


一、测试场景总览:3577 号用例在验证什么

test/command/3577.md是 Pandoc 命令测试套件(test/Command.hs)中的一个用例,文件内以标准格式记录了“输入命令 + 输入内容(以^D结束的 stdin)+ 期望输出”。它包含两个子场景:

场景输入关注点
场景一一个外层figure内嵌两个subfigure,每个子图各有\includegraphics\caption,外层另有总\caption嵌套<figure>的层级、两个子图题注 + 总题注的映射关系
场景二一个普通figure,含单张图片与\caption基础figure环境的转换、data-latex-placement属性

这个用例的核心目标,是确保 LaTeX 中“图中有子图”的经典排版(subcaption 宏包风格)在转成 HTML5 后,语义结构依然完整保留:外层一个figure承载总题注,内层每个subfigure各自成为独立的figure并携带自己的题注

二、完整转换示例与逐行解析

2.1 场景一:包含 subfigure 的嵌套 figure

输入命令与 LaTeX 内容如下:

% pandoc -f latex -t html5 --quiet \begin{figure}[ht] \begin{subfigure}{0.45\textwidth} \centering \includegraphics{img1.jpg} \caption{Caption 1} \end{subfigure} \begin{subfigure}{0.45\textwidth} \centering \includegraphics{img2.jpg} \caption{Caption 2} \end{subfigure} \caption{Subfigure with Subfloat} \end{figure}

Pandoc 输出(已与测试期望比对):

<figure>% pandoc -f latex -t html5 \begin{figure}[ht] \includegraphics{img1.jpg} \caption{Caption 3} \end{figure}

输出:

<figure>pandoc -f latex -t html5 --quiet <<'EOF' \begin{figure}[ht] \includegraphics{img1.jpg} \caption{Caption 3} \end{figure} EOF
  • -f latex:指定输入格式为 LaTeX;
  • -t html5:指定输出格式为 HTML5(输出<figure>/<figcaption>语义标签);
  • --quiet:抑制警告信息,保证输出干净,便于与期望结果做 diff。

方式二:文件输入

pandoc input.tex -t html5

测试期望输出分别保存在 test/command/3577.md 的代码块中;整个命令测试套件通过 test-pandoc.hs 驱动运行,核心断言逻辑可参考 test/Command.hs。

四、源码级原理:LaTeX 读取器如何解析 figure/subfigure

4.1 环境注册

在 LaTeX 读取器 src/Text/Pandoc/Readers/LaTeX.hs 中,三个环境被统一注册到解析表:

("figure", env "figure" figure') ("figure*", env "figure*" figure') ("subfigure", env "subfigure" $ skipopts *> tok *> figure')
  • figurefigure*直接交给解析函数figure'figure*是双栏排版中跨栏的通栏图环境);
  • subfigure稍有不同:skipopts先跳过可选的[位置]参数,tok再消费掉{0.45\textwidth}这样的宽度参数,然后才进入与普通figure相同的figure'解析逻辑——这正是子图能被解析成“独立 figure 块”的原因。

4.2 figure' 的解析流程

核心解析函数位于 src/Text/Pandoc/Readers/LaTeX.hs,关键步骤:

figure' = try $ do sp poshint <- option "" $ untokenize <$> bracketedToks -- 捕获 [ht] 放置参数 sp resetCaption -- 重置题注收集器 innerContent <- many $ try (Left <$> label) <|> (Right <$> block) ... let kvs = [("latex-placement", poshint) | not (T.null poshint)] let ident = fromMaybe "" mblabel let attr = (ident, [], kvs) ... return $ B.figureWith attr caption' content

对应关系:

  1. [ht]放置参数:通过bracketedToks读取环境开头的方括号内容,存入poshint,随后以键值对("latex-placement", poshint)写入图块的属性。这就是输出中data-latex-placement="ht"的来源。
  2. resetCaption:在进入环境体之前重置题注状态,保证之后遇到的\caption能被正确归属。
  3. \label处理:环境内出现的\label{...}会被单独捕获,成为图块的标识符(ident);同时读取器会为带标签的图维护编号(getNextNumber sLastFigureNum),使后续\ref能解析出正确的图号(以点分编号如1.1形式存储于sLabels)。
  4. 构建 Figure 块:最终通过B.figureWith attr caption' content构造出 Pandoc 的Figure块,属性中携带标识符、空 class 和latex-placement键值对。

另外,figure'内的辅助函数go专门处理图片占位文本:

go (Para [Image attr [Str "image"] target]) = Plain [Image attr [] target]

即把\includegraphics转换出的“图片 + 隐式 alt('image')”简化为空 alt 的图片,因为真正的题注文本已被提升到Figure的 caption 上。这解释了输出中<img src="img1.jpg" />为什么没有 alt 属性。

五、中间表示与 HTML 写入器渲染

5.1 统一的 Figure 块

无论输入是figurefigure*还是subfigure,LaTeX 读取器最终都产出同一个Figure块。在 HTML 写入器 src/Text/Pandoc/Writers/HTML.hs 中:

blockToHtmlInner opts (Figure attrs (Caption _ captBody) body) = do html5 <- gets stHtml5 ... let figCaption = if html5 then [ H5.figcaption ! fcattr $ captCont ] -- HTML5: <figcaption> else [ (H.div ! A.class_ "figcaption") captCont ] -- HTML4: div.figcaption ... if html5 then foldl (!) H5.figure figAttrs innards -- HTML5: <figure> else foldl (!) H.div (A.class_ "float" : figAttrs) innards -- HTML4: div.float

由此可以明确:

  • HTML5 输出使用<figure>+<figcaption>HTML4 输出则退化为div.float+div.figcaption
  • 图块属性attrs全部经attrsToHtml渲染,未识别的键(如latex-placement)按 Pandoc 规则输出为data-*自定义属性,因此latex-placement变成了data-latex-placement
  • 题注位置可通过写入选项writerFigureCaptionPosition(命令行对应--figure-caption-position=above|below)控制:CaptionBelow时图片在前、题注在后(即默认的测试输出形态),CaptionAbove时两者互换。

5.2 嵌套结构的形成

因为内层subfigure被解析为独立的Figure块,它们作为外层Figurebody内容被blockListToHtml逐一渲染,自然形成了“外层<figure>内嵌套两个<figure>”的 DOM 层级;而外层Figure的 caption 是总题注,渲染为最外层的<figcaption>,与测试期望完全一致。

六、延伸场景与注意事项

  1. 双栏通栏图:使用\begin{figure*}时,读取器走完全相同的figure'逻辑(见 src/Text/Pandoc/Readers/LaTeX.hs),因此也能得到同样的<figure contenteditable="false">【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询