Monday, October 6, 2014

Uppercasing in a "memoir" Table of Contents with "hyperref"

memoir is one of my favorite document classes in LaTeX, but uppercased headings in a memoir table of contents conflict with the hyperref package. Uppercasing headings the table of contents in a memoir document can be achieved in at least two basic ways. The first uses the \cftKfont font commands to send formatting instructions to the table of contents. The K in \cftKfont stands for the heading level,1 so to modify the chapter headings, for example, you would use the \cftchapterfont macro as shown below:

% Uppercase chapter headings in TOC
\renewcommand*{\cftchapterfont}%     
  {\normalfont\MakeUppercase}

Because \MakeUppercase is sort of brutal in the way that it uppercases, it can cause errors. The memoir documentation recommends using another macro \MakeTextUppercase, which would be used in the following way to uppercase chapter headings in the table of contents:

% Uppercase chapter headings in TOC
\renewcommand*{\cftchapterfont}%     
  {\normalfont\MakeTextUppercase}

These methods are simple, but—as noted above—they both conflict with the hyperref package.

This conflict is aggravating because hyperref makes PDFs better in many ways. For example, hyperref will automatically make internal document links active. So if you have citations throughout your work, those in-text citations will turn into links that jump down to their entries in the list of citations at the end of the document. Similarly, when the document refers to a table or figure (e.g., “see table 2 for more information”), the number becomes an internal document link that will take the reader to the table or figure. And entries in the table of contents also become internal document links. So there are a lot of benefits to simply using the following line in a preamble:

\usepackage{hyperref}

With specific commands, hyperref can do a lot more, such as write out PDF metadata and use another package, called bookmarks, to create a PDF navigation bar.

The conflict between these two uppercasing commands and hyperref are a known problem, so memoir provides another method, \settocpreprocessor, for sending uppercase formatting to headings in the table of contents (see p. 158 of the memoir documentation). The code below shows how to use this macro to uppercase part and chapter headings in the table of contents:

\makeatletter
\settocpreprocessor{part}{%
    \let\tempf@rtoc\f@rtoc%
    \def\f@rtoc{%
      \texorpdfstring{\MakeTextUppercase{%
        \tempf@rtoc}%
      }{\tempf@rtoc}%
    }% 
}
\settocpreprocessor{chapter}{%
    \let\tempf@rtoc\f@rtoc% 
    \def\f@rtoc{%
      \texorpdfstring{\MakeTextUppercase{%
        \tempf@rtoc}%
      }{\tempf@rtoc}%
    }% 
}
\makeatother

This code will uppercase part and chapter heading entries in the table of contents, but it does not uppercase part-level or chapter-level headings in the table of contents. The difference is important because entries, such as the “List of tables,” won’t be uppercased by these commands. Doesn’t it make more sense for entries with the same level to have the same formatting? Users can get around this problem by manually uppercasing table-of-contents entries, such as for the name of the list of tables:

% Manually uppercase name of the list of tables
\renewcommand{\listtablename}
  {LIST OF TABLES}

But users would need to go back and manually change this and other commands if they want to produce a new version of their document without uppercased part-level and chapter-level headings. This approach violates the supposed strength of LaTeX—separating content from formatting. Instead, users need a way to uppercase part-level headings and chapter-level headings in memoir documents.

Fortunately, I have discovered a way to produce uppercase part-level and chapter-level headings by patching certain macros in the memoir document class. In the preamble, enter the following:

% Load 'etoolbox' to get the '\patchcmd' macro
\usepackage{etoolbox}

% Patch the command that writes part-level entries
%   to the table of contents, so they are in 
%   'normalfont' and uppercase
\makeatletter% 
\patchcmd{\l@part}%                     
    {\cftpartfont {#1}}%                
    {\normalfont \texorpdfstring{%      
      \uppercase{#1}}{{#1}} }%
    {\typeout{Success: Patch %
      'l@part' to uppercase %
      part-level headings in the %
      table of contents.}}%
    {\typeout{Fail: Patch %
      'l@part' to uppercase % 
      part-level headings in the %
      table of contents.}}%
\makeatother%

% Patch the command that writes chapter-level 
%   entries to the table of contents, so they are 
%   in 'normalfont' and uppercase
\makeatletter% 
\patchcmd{\l@chapapp}%                  
    {\cftchapterfont {#1}}%             
    {\normalfont \texorpdfstring{%      
      \uppercase{#1}}{{#1}} }%
    {\typeout{Success: Patch %
      'l@chapapp' to uppercase %
      part-level headings in the %
      table of contents.}}%
    {\typeout{Fail: Patch %
      'l@chapapp' to uppercase %
      part-level headings in the %
      table of contents.}}%
\makeatother%

% Load 'hyperref' to get the \texorpdfstring
%   command
\usepackage{hyperref}

This solution uses a similar approach to the one provided in memoir documentation with the \settocpreprocessor macro in that both use the \texorpdfstring macro from the hyperref package. The \texorpdfstring macro lets users send different text depending on whether the text will be typeset by LaTeX or not. Chapter headings are an example of content that gets typeset by LaTeX in the table of contents and in the PDF as PDF bookmarks, so \texorpdfstring is a great way to avoid these kinds of errors.


Notes:


  1. See table 9.3 on p. 150 of the memoir documentation for the other values of K.

No comments:

Post a Comment