[Tex/LaTex] Change format of hyperref generated PDF bookmarks

bookmarkshyperrefnumbering

In a generic way, how can I change the format of bookmarks generated automatically by hyperref (or bookmark)?

By generic, I mean the ability the customize the bookmark format for part, chapter, section, etc. without having to modify the document TeX. Ideally it will be contained in a class wrapper.

Bookmark format ideas:

  • Unnumbered parts, numbered chapters, unnumbered sections/subsections (but they all are numbered – not@star).
  • Part format: "Part <#>: " or ", Part <#>"
  • Move number to after the title

MWE:

\document{scrbook}
\usepackage{hyperref}
\usepackage[numbered]{bookmark}
\begin{document}
\part{Test Part}
\chapter{Test Chapter}
\section{Test Section}
\part{Test Part}
\chapter{Test Chapter}
\section{Test Section}
\end{document}

Here's the index output (evince) marked up with what I would like to do. Perhaps rewriting a bookmark/hyperref command would do?

sample output

Best Answer

The following provides the functionality to swap titles and numbers in the bookmarks:

enter image description here

\documentclass{scrbook}% http://ctan.org/pkg/KOMA-script
% \usepackage{hyperref}% http://ctan.org/pkg/hyperref
\usepackage[numbered]{bookmark}% http://ctan.org/pkg/bookmark
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox

\makeatletter
\let\store@Hy@writebookmark\Hy@writebookmark
% Argument patching inside a macro: https://tex.stackexchange.com/q/113147/5764
\catcode`\#=12
% Swap num/title in bookmarks
\newcommand{\reversetitlenumswap}{%
  % \patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
  \patchcmd{\Hy@writebookmark}{#2}{\BKM@reversetitle}{}{}%
  \patchcmd{\Hy@writebookmark}{\bookmark}{\let\numberline\@gobble\edef\BKM@reversetitle{#2\ #1}\bookmark}{}{}%
}
\catcode`\#=6
\newcommand{\reverttitlenumswap}{\let\Hy@writebookmark\store@Hy@writebookmark}% Revert num/title swap in bookmarks
% Section-specific swapping of num/title in bookmarks
\newcommand{\parttitlenumswap}{\renewcommand{\addparttocentry}[2]{{\reversetitlenumswap\addtocentrydefault{part}{##1}{##2}}}}
\newcommand{\chaptertitlenumswap}{\renewcommand{\addchaptertocentry}[2]{{\reversetitlenumswap\addtocentrydefault{chapter}{##1}{##2}}}}
\newcommand{\sectiontitlenumswap}{\renewcommand{\addsectiontocentry}[2]{{\reversetitlenumswap\addtocentrydefault{section}{##1}{##2}}}}
\makeatother

\begin{document}

\parttitlenumswap% Swap \part num/title in bookmarks
\sectiontitlenumswap% Swap \section num/title in bookmarks

\part{Test Part}
\chapter{Test Chapter}
\section{Test Section}

\part{Test Part}
\chapter{Test Chapter}
\section{Test Section}

\end{document}

The above MWE provides \reversetitlenum that acts as a switch. After calling this macro, all subsequent sectional units will have a swapped number/title in the bookmarks. \reverttitlenum is a switch that reverts back to the default presentation.

Separate macros for each sectional unit (\part, \chapter and \section, although other can also be defined as needed) is also provided to selectively activate the swapping of bookmark constructions.

The main approach to this solution is to hack into \Hy@writebookmark - the macro that is finally called to construct the bookmark (from bookmark.dtx):

\def\Hy@writebookmark#1#2#3#4#5{%
  \ifnum#4>\BKM@depth\relax
  \else
    \def\BKM@type{#5}%
    \ifx\BKM@type\Hy@bookmarkstype
      \begingroup
        \ifBKM@numbered
          \let\numberline\Hy@numberline
          \let\booknumberline\Hy@numberline
          \let\partnumberline\Hy@numberline
          \let\chapternumberline\Hy@numberline
        \else
          \let\numberline\@gobble
          \let\booknumberline\@gobble
          \let\partnumberline\@gobble
          \let\chapternumberline\@gobble
        \fi
        \bookmark[level=#4,dest={#3}]{#2}%
      \endgroup
    \fi
  \fi
}

It takes 5 arguments of which the first 2 are the most important from a visual/end user perspective. #1 contains the sectional unit number <num> (although it is never used), while #2 contains a ToC-like entry of the form \protect\numberline{<num>}<title>. The default is to only use #2. The suggested patch in \reversetitlenumswap uses both, printing it as #2\ #1 while also temporarily deactivating the macro \numberline. The patch is inserted just above the \bookmark entry, while also updating the use of only #2 (resulting in two separate patches).

It is not necessary to load hyperref. bookmark loads hyperref and uses some of its code. See Which package should I load first: hyperref or bookmark?