使用 endfloat 时,使用 \caption 在 \includegraphics 下方渲染图形上方的标题

使用 endfloat 时,使用 \caption 在 \includegraphics 下方渲染图形上方的标题

背景:我的 TeX 文件是由 R Markdown 生成的,标题会自动放置在包含的图形下方。下面是我生成的 TeX 文件的一个最小示例:

\documentclass[man]{apa7}
\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
The figure
\caption{The caption.}
\end{figure}

\end{document}

问题:需要渲染图片标题多于相应的图形(根据 APA 指南)无需移动\caption

我尝试过floatrow:我理解,无需通过包和更改代码,标题就可以呈现在图形上方\floatsetup[figure]{style=plaintop}。但是,加载floatrow会干扰endfloat由加载的apa7。具体来说,图形不再放在文档末尾,而是呈现在原地:

\documentclass[man]{apa7}
\usepackage{floatrow}
\floatsetup[figure]{style=plaintop}

\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
The figure
\caption{The caption.}
\end{figure}

\end{document}

根据 的文档endfloatfloatrow应始终在 之前加载endfloat(因此,在 之前apa7)。因此,我尝试floatrow通过加载\RequirePackage{},但这会产生错误。我可以通过取消定义两个长度来修复其中一些问题,但这会给我带来以下错误,我似乎无法解决:

! Missing \endcsname inserted.
<to be read again> 
                   \@classoptionslist 
l.1453 \ProcessOptionsWithKV{floatrow}

这是最小的可重现示例:

\RequirePackage{floatrow}
\let\abovecaptionskip\undefined
\let\belowcaptionskip\undefined

\documentclass{apa7}

\begin{document}

Lorem ipsum

\end{document}

请注意,尽管出现错误消息,但我得到的渲染 PDF 文件看起来与预期一致。此外,这并非特定于;当我使用或文档类apa7时,我遇到了同样的错误。articlebook

答案1

有趣的是,apa7 会转换figurefigure*。无论如何,基本思想是将标题和图形存储到单独的保存箱中并反转它们的顺序。

\documentclass[man]{apa7}
%\documentclass{article}
%\usepackage{endfloat}
\usepackage{lipsum}% MWE only

% udbox is a \vbox version of lrbox
\makeatletter
\def\udbox#1{%
  \edef\reserved@a{%
  \endgroup
  \setbox#1\vbox{%
  \begingroup\aftergroup}%
  \def\noexpand\@currenvir{\@currenvir}%
  \def\noexpand\@currenvline{\on@line}}%
  \reserved@a
  \@endpefalse
  \color@setgroup
  \ignorespaces}
\def\endudbox{\unskip\color@endgroup}
\makeatother

\newsavebox{\mycaptionbox}
\newsavebox{\myfigurebox}

\makeatletter
\let\normalmakecaption=\@makecaption
\def\@makecaption#1#2{\def\test{figure}%
  \ifx\@captype\test \global\setbox\mycaptionbox=\vbox{\normalmakecaption{#1}{#2}}%
  \else \normalmakecaption{#1}{#2}%
  \fi}
\makeatother

\let\normalfigure=\figure
\let\endnormalfigure=\endfigure

\renewenvironment{figure}[1][tbp]{\normalfigure
  \begin{udbox}{\myfigurebox}}%
{\end{udbox}\unvbox\mycaptionbox
  \unvbox\myfigurebox\endnormalfigure}

\expandafter\let\expandafter\normalfigurestar\csname figure*\endcsname
\expandafter\let\expandafter\endnormalfigurestar\csname endfigure*\endcsname

\renewenvironment{figure*}[1][tbp]{\normalfigurestar
  \begin{udbox}{\myfigurebox}}%
{\end{udbox}\unvbox\mycaptionbox
  \unvbox\myfigurebox\endnormalfigurestar}

\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
\lipsum[1]
\caption{The caption.}
\end{figure}

\end{document}

答案2

efloat正在对 进行重新定义figurefigure*并且\efloat@AtBeginDocument通常\efloat@AtBeginDocument被定义为 或\@iden\AtBeginDocument在这种情况下,两者都会过早地进行重新定义,因为floatrow包会进行重新定义\AtBeginDocument。因此,解决您的问题的诀窍是endfloat进一步延迟包进行的重新定义。

幸运的是,的定义\efloat@AtBeginDocument已经完成,\providecommand因为的作者efloat已经考虑给用户一个选项来自行确定重新定义的确切时间:“(注意:\efloat@AtBeginDocument 将使用 \providecommand 定义,因此文档类和包可以在需要时对其进行预定义。)”(引自代码文档efloat

下面的解决方案定义了它自己的版本\efloat@AtBeginDocument,将内容存储到一个名为的宏中\efloatredefinitions,该宏可以在以后应用,特别是在包的重新定义floatrow已经完成之后。

% Store the code of efloat re-definitions into \efloatredefinitions
% (This code must be defined before the efloat package is loaded.)
\makeatletter
\newcommand\efloatredefinitions{}
\newcommand\efloat@AtBeginDocument{\g@addto@macro\efloatredefinitions}
\makeatother

\documentclass[man]{apa7}

\usepackage{floatrow}
\floatsetup[figure]{style=plaintop}

% Do the efloat re-definitions after the re-definitions of floatrow were done
%\show\efloatredefinitions
\AtBeginDocument{\efloatredefinitions} % or simply \efloatredefinitions after \begin{document}

\title{Test}

\begin{document}
\maketitle

Lorem ipsum

\begin{figure}
The figure
\caption{The caption.}
\end{figure}

\end{document}

endfloatPS:如果包中能提供“storeredefinitions”或类似选项,这样\PassOptionsToPackage{storeredefinitions}{endfloat}就可以使用,而不是单独定义,那就太好了\efloat@AtBeginDocument。将给作者写一封电子邮件endfloat...

相关内容