6

I am able to automatically make the first sentence of a float caption bold by following the approach given at Automatically bold first sentence of a floats caption. However, when I use the hyperref package, this method no longer works.

In the following MWE, the automatic bolding works or doesn't when \usepackage{hyperref} is commented or uncommented, respectively.

\documentclass{article}
\usepackage{caption}
\usepackage{etoolbox}
\usepackage{xstring}

\makeatletter
\newcommand\formatlabel[1]{%
    \noexpandarg
    \IfSubStr{#1}{.}{%
      \StrBefore{#1}{.}[\firstcaption]%
      \StrBehind{#1}{.}[\secondcaption]%
      \textbf{\firstcaption.} \secondcaption}{%
      #1}%
      }
\patchcmd{\@caption}{#3}{\formatlabel{#3}}
\makeatother

\usepackage{hyperref}

\begin{document}

\begin{figure}[tb]
    \caption{First sentence that should be bold. Second sentence should not be.}
    \label{fig:figure1}
\end{figure}

\end{document}

Is there an alternative way to make the first sentence bold that works with hyperref?

hugke729
  • 163

2 Answers2

2

When hyperref is loaded, the command \@caption is redefined so that the third argument #3 appears three different places in the code rather than just once. It seems that you just need to replace the third occurrence which is #3\fi to get your desired effect.

Sample output

\documentclass{article}
\usepackage{caption}
\usepackage{etoolbox}
\usepackage{xstring}
\usepackage{hyperref}

\makeatletter
\newcommand\formatlabel[1]{%
    \noexpandarg
    \IfSubStr{#1}{.}{%
      \StrBefore{#1}{.}[\firstcaption]%
      \StrBehind{#1}{.}[\secondcaption]%
      \textbf{\firstcaption.} \secondcaption}{%
      #1}%
      }
%\patchcmd{\@caption}{\ignorespaces #3}{\ignorespaces\formatlabel{#3}}{}{}
%\patchcmd{\@caption}{{#3}}{{\formatlabel{#3}}}{}{}
\patchcmd{\@caption}{#3\fi}{\formatlabel{#3}\fi}{}{}
\makeatother



\begin{document}

\begin{figure}[tb]
    \caption{First sentence that should be bold. Second sentence should not be.}
    \label{fig:figure1}
\end{figure}

\end{document}

In the above, the two commented lines would apply patches to the other two occurrences of the use of the third argument if needed.

You can display the definition of \@caption in the log file via \show\@caption.

Andrew Swann
  • 95,762
2

The definition of \@caption contains the third argument more than once, from package caption (\@caption will redefined to become \caption@@caption):

\long\def\caption@@caption#1[#2]#3{%
  \ifcaption@star \else
    \caption@prepareanchor{#1}{#2}%
    \memcaptioninfo{#1}{\csname the#1\endcsname}{#2}{#3}%
    \@nameuse{nag@hascaptiontrue}%
  \fi
  \par
  \caption@beginex{#1}{#2}{#3}%
    \caption@setfloatcapt{%
      \caption@boxrestore
      \if@minipage
        \@setminipage
      \fi
      \caption@normalsize
      \ifcaption@star
        \let\caption@makeanchor\@firstofone
      \fi
      \@makecaption{\csname fnum@#1\endcsname}%
                   {\ignorespaces\caption@makeanchor{#3}}\par
      \caption@if@minipage\@minipagetrue\@minipagefalse}%
  \caption@end
}

Thus \patchcmd only replaced the first occurrence. BTW, \patchcmd has two additional arguments for code in case of success or failure.

The following example uses a different method. Macro \formatlabel is introduced by a "chained" redefinition. Also this is moved to \AtBeginDocument for caption to see the old definition.

\documentclass{article}
\usepackage{caption}
\usepackage{xstring}
\usepackage{hyperref}

\makeatletter
\newcommand\formatlabel[1]{%
    \noexpandarg
    \IfSubStr{#1}{.}{%
      \StrBefore{#1}{.}[\firstcaption]%
      \StrBehind{#1}{.}[\secondcaption]%
      \textbf{\firstcaption.} \secondcaption}{%
      #1}%
}
\AtBeginDocument{%
  \newcommand*{\org@caption}{}%
  \let\org@caption\@caption
  \def\@caption#1[#2]#3{%  
    \org@caption{#1}[{#2}]{\formatlabel{#3}}%
  }%
}   
\makeatother

\begin{document}

\begin{figure}[tb]
  \caption{First sentence is bold. Second sentence is not.}
  \label{fig:figure1}
\end{figure}

\end{document}

Result

Heiko Oberdiek
  • 271,626
  • The latter method worked with the added benefit that I no longer receive a warning from the caption package. – hugke729 May 05 '15 at 16:04