10

I'm trying to use hyperref on a very large number of section headings for pieces of artwork in a document, but I have to use a workaround to get the title of the artwork into a bookmark of the section:

\documentclass{article}

\usepackage[backend=biber]{biblatex}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@ARTWORK{gizapyramid,
  title = {Pyramids at Gizeh},
  year = {ca.\@ 2500 BCE}
}
\end{filecontents}
\addbibresource{\jobname.bib}

\usepackage[hidelinks]{hyperref}

\begin{document}

\section{\texorpdfstring%
{\citetitle{gizapyramid} (\citedate{gizapyramid})}%
{Pyramids at Gizeh}}

\end{document}

Doing that properly displays "Pyramids at Gizeh" in the bookmark; however, since I occasionally find myself tweaking the title of various artworks to more accurately match common names, I would like to do something like this:

\documentclass{article}

\usepackage[backend=biber]{biblatex}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@ARTWORK{gizapyramid,
  title = {Pyramids at Gizeh},
  year = {ca.\@ 2500 BCE}
}
\end{filecontents}
\addbibresource{\jobname.bib}

\usepackage[hidelinks]{hyperref}

\begin{document}

\section{\texorpdfstring%
{\citetitle{gizapyramid} (\citedate{gizapyramid})}%
{\citetitle{gizapyramid}}}

\end{document}

The problem with that is it throws the warning:

Package hyperref Warning: Token not allowed in a PDF string (PDFDocEncoding): (hyperref) removing `\citetitle' on input line 20.

Then, it displays the tag "gizapyramid" in the bookmark instead of "Pyramids at Gizeh" as desired.

How can I make \citetitle work in a hyperref section bookmark like I want without ruining its normal behavior elsewhere in the document?

3
  • Basically you can't. The bookmarks accepts essentially only strings of characters, not the instructions needed to produce them.
    – egreg
    Sep 22, 2012 at 21:17
  • @egreg Would it not be possible to somehow define a string variable from an evaluation of the instructions, then pass that onto the bookmark?
    – GPhys
    Sep 22, 2012 at 21:24
  • @Gnintendo That is possible, but the string macro must be expandable. To ensure this, you need to access unformatted data via an indexing or formatting directive. Heiko's answer is good for fields. For names, see: tex.stackexchange.com/q/60552/4483.
    – Audrey
    Sep 23, 2012 at 16:20

2 Answers 2

9

You can profit of my usebib package:

\documentclass{article}

\usepackage[backend=biber]{biblatex}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@ARTWORK{gizapyramid,
  title = {Pyramids at Gizeh},
  year = {ca.\@ 2500 BCE}
}
\end{filecontents}
\addbibresource{\jobname.bib}

\usepackage[hidelinks]{hyperref}

\usepackage{usebib}
\bibinput{\jobname}

\begin{document}

\section{\texorpdfstring%
{\citetitle{gizapyramid} (\citedate{gizapyramid})}%
{\usebibentry{gizapyramid}{title}}}


\end{document}

enter image description here

8

Bookmark strings need to be converted to PDF strings. The main step is expanding the string to get rid of the TeX/LaTeX commands. However many commands do not work in expandable contexts. Some left "garbage" that is filtered out by \pdfstringdef or some undesired stuff remains in the bookmark or the macro even breaks.

The \cite... commands of biblatex will not work in expandable contexts and are not supported in bookmarks. They are even protected macros (by e-TeX's \protected). That makes it easy to filter them out and give a proper warning.

As workaround, the title can be extracted outside the bookmarks and stored in a macro that is used in the bookmarks:

\documentclass{article}

\usepackage[backend=biber]{biblatex}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@ARTWORK{gizapyramid,
  title = {Pyramids at Gizeh},
  year = {ca.\@ 2500 BCE}
}
\end{filecontents}
\addbibresource{\jobname.bib}

\usepackage{hyperref}
\usepackage{bookmark}

\makeatletter
\newcommand*{\StoreCiteField}[3]{%
  \begingroup
    \global\let\StoreCiteField@Result\relax
    \citefield{#2}[StoreCiteField]{#3}%
  \endgroup
  \let#1\StoreCiteField@Result
}
\DeclareFieldFormat{StoreCiteField}{%
  \gdef\StoreCiteField@Result{#1}%
}
\makeatother

\begin{document}

\StoreCiteField\TitleGizapyramid{gizapyramid}{title}
\section{\texorpdfstring
{\citetitle{gizapyramid} (\citedate{gizapyramid})}%
{\TitleGizapyramid}}

\end{document}

I have used a detour via a formatting command to get the data. Are there side effects of \citefield that should be taken care of? Do better ways exist?

11
  • 1
    +1: Could this be expanded (as a separate question) so that it works with author? \citefield{key}{author} is nor possible with biblatex (tex.stackexchange.com/questions/207591). Feb 21, 2022 at 23:59
  • 1
    NVM, I was able to use: \newcommand*{\StoreAuthor}[2]{% \begingroup \global\let\StoreAuthor@Result\relax \citeauthor{#2}% \endgroup \let#1\StoreAuthor@Result } \DeclareFieldFormat{StoreAuthor}{% \gdef\StoreAuthor@Result{#1}% } Feb 22, 2022 at 0:06
  • Aaahh! This is the kind of thing I was looking for ... :).
    – cfr
    Mar 20, 2022 at 2:00
  • @Dr.ManuelKuehner I can't figure it out for the author case, though. The code you've given doesn't seem to use the StoreAuthor format you define?
    – cfr
    Mar 20, 2022 at 4:58
  • 1
    @Dr.ManuelKuehner i put it in chat for now because it is really ... er ... early? simple-minded? But if you think it would be useful after actually seeing it, I'll post it there. (I did consider that but it just seemed too crappy.) I've even got an MWE for it because I wanted something quicker than a real document.
    – cfr
    Mar 20, 2022 at 6:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .