4

I'm having trouble getting an ampersand to show up in the PDF table of contents in a document structured like so:

\documentclass{article}

\usepackage{hyperref}

\ExplSyntaxOn

\prop_const_from_keyval:Nn \c_mwe_test_prop {
    A = { Simple~and~Problem~Free },
    B = { Complex~\&~Bugged },
}

\NewExpandableDocumentCommand{\gettest}{m}{\prop_item:Nn \c_mwe_test_prop {#1}}

\ExplSyntaxOff

\NewExpandableDocumentCommand{\ampersand}{}{\&}

\begin{document}

\section{Experiment \& Test}

Works fine.

\section{Experiment \ampersand{} Test}

Works fine.

\section{\gettest{A}}

Works fine, too.

\section{\gettest{B}}

Works fine in the document, but not in PDF bookmarks.

\end{document}

The document has four sections. The first two just demonstrate that hyperref normally copes fine with a \& in a \section, even if it's hidden behind a macro. The third and fourth show the section title being retrieved from an expl3 property list. Both work fine within the document itself, but the ampersand is lost in the PDF bookmarks:

Token not allowed in a PDF string (Unicode):
(hyperref)  removing `\&'.

It feels like something is going wrong with the expansion order here. Notably, trying to replace the \& with \texorpdfstring{\&}{and} in the property list assignment yields this warning:

Token not allowed in a PDF string (Unicode):
(hyperref)  removing `\texorpdfstring'.

How can I get hyperref to properly write out the ampersand (while still getting the section titles from a property list)?

5
  • 1
    The problem is the same as here: \prop_item:Nn returns the item wrapped in \unexpanded, but hyperref relies on redefining \& to expand to a PDF string in that context (and \unexpanded doesn't allow that). If you are sure your text works in an expansion context, you can use \NewExpandableDocumentCommand{\gettest}{m} { \use:e { \prop_item:Nn \c_mwe_test_prop {#1} } } Oct 21 at 14:27
  • @PhelypeOleinik one could perhaps disable \exp_not:n in the pdf strings with \pdfstringdefDisableCommands{\cs_set_eq:NN\exp_not:n\prg_do_nothing:} Oct 21 at 15:03
  • @PhelypeOleinik, using \use:e works in my context and fixes the problem – thank you!
    – fefrei
    Oct 21 at 15:06
  • 1
    @fefrei Posted that as an answer. Actually, even if your text has fragile macros, they won't explode with \use:e because the \unexpanded protects them (though they can still break in \pdfstringdef if they don't have a defined pdfstring equivalent). Oct 21 at 15:38
  • @UlrikeFischer Not sure: any expl3 code that ends up in there can break if you disable \exp_not:n. It would be safer to constrain the change to \prop_item:Nn with something like \cs_set:Npn \prop_item:Nn #1 #2{ \use:e { \actual_prop_item:Nn #1 {#2} } }. Oct 21 at 15:42
6

The problem is the same as here: \prop_item:Nn returns the item wrapped in \unexpanded (so it can be safely used, for example, in \tl_set:Nx \l_tmpa_tl { \prop_item:Nn \l_tmpa_prop { my-item } } without exploding), but hyperref relies on redefining \& to expand to a PDF string in that context (and \unexpanded doesn't allow that).

You can add \use:e (\expanded) in your macro so that it removes the \unexpanded before hyperref has the chance to see it:

\documentclass{article}

\usepackage{hyperref}

\ExplSyntaxOn

\prop_const_from_keyval:Nn \c_mwe_test_prop {
    A = { Simple~and~Problem~Free },
    B = { Complex~\&~Bugged },
}

\NewExpandableDocumentCommand{\gettest}{m}
  { \use:e { \prop_item:Nn \c_mwe_test_prop {#1} } }

\ExplSyntaxOff

\NewExpandableDocumentCommand{\ampersand}{}{\&}

\begin{document}

\section{Experiment \& Test}

Works fine.

\section{Experiment \ampersand{} Test}

Works fine.

\section{\gettest{A}}

Works fine, too.

\section{\gettest{B}}

Works fine in the document, but not in PDF bookmarks.

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.