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に干渉します。具体的には、図はドキュメントの末尾に配置されなくなり、その場でレンダリングされます。endfloatapa7

\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}

のドキュメントによればendfloat、は常に の前に(したがって の前に)floatrowロードされる必要があります。したがって、 を介してロードしようとしますが、エラーが発生します。2 つの長さを未定義にすることでこれらのエラーの一部を修正できますが、解決できない次のエラーが残ります。endfloatapa7floatrow\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

興味深いことに、apa7figureは に変換されますfigure*。とにかく、基本的な考え方は、キャプションと図を別々の保存ボックスに保存し、順序を逆にすることです。

\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の再定義を 内部で行っておりfigure、通常はまたはとして定義されます。この場合、パッケージが の再定義を行うため、どちらも再定義を行うのが早すぎます。したがって、この状況を解決する秘訣は、パッケージによる再定義をさらに遅らせることです。figure*\efloat@AtBeginDocument\efloat@AtBeginDocument\@iden\AtBeginDocumentfloatrow\AtBeginDocumentendfloat

幸いなことに、 の定義は\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

関連情報