使用 PDF 中的正确 TOC 链接自定义单个 \part 分段命令?

使用 PDF 中的正确 TOC 链接自定义单个 \part 分段命令?

我想使用一个\part(所以不是全部)作为编号分段命令(所以没有\part*),但我想为实际部分标题设置一个单独的条目,为 PDF 中排版的目录设置一个单独的条目,并为 PDF 书签中的目录设置一个单独的条目。

通过以下 MWE,我几乎可以实现所有这些:

\documentclass{book}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{hyperref}

% http://stackoverflow.com/questions/2785260/hide-an-entry-from-toc-in-latex
\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[2]{\bgroup\let\addcontentsline=\nocontentsline#1{#2}\egroup}

% copy of hyperref.sty \phantomsection:
\makeatletter
\def\phantompart{%
  \Hy@MakeCurrentHrefAuto{part}%
  \Hy@raisedlink{\hyper@anchorstart{\@currentHref}\hyper@anchorend}%
}
\makeatother


\begin{document}

\tableofcontents

\chapter*{Important notes}

A very important part comes ahead.

\section{A numbered section}

This should show in the TOC, too...

\def\ptitle{Test title}

\tocless\part{%
  \texorpdfstring{%
    % tex string for \part itself
    Introduction: \emph{\ptitle} - \textbf{and more}. %
  }{%
    % pdf string for PDF Bookmarks TOC
    Introduction: \ptitle%
  }%
}
% tex string for the PDF typeset TOC
% \refstepcounter{part} - already done!
% \phantompart % for correct links in \addcontentsline
% \thepart \hspace{1em} from def of @part in book.cls:
\addcontentsline{toc}{part}{\thepart\hspace{1em} Introduction: \emph{\ptitle}.}

Something in this part...

\chapter{Inside the part}

The chapter inside the part...

\section{More inside the part}

The section more inside the part...

\end{document}

... 除了目录链接是错误的;没有\phantompart(通过类比实现,据说\phantomsection可以解决这类问题),该test.toc文件包含一个正确命名的链接(part.1),但页码错误(7):

\contentsline {section}{\numberline {0.1}A numbered section}{3}{section.0.1}
\contentsline {part}{I\hspace {1em} Introduction: \emph {Test title}.}{7}{part.1}
\contentsline {chapter}{\numberline {1}Inside the part}{9}{chapter.1}
\contentsline {section}{\numberline {1.1}More inside the part}{9}{section.1.1}

... 而\phantompart没有注释掉的部分,情况就更糟了——错误命名的链接(part.3),以及错误的页码(7):

\contentsline {section}{\numberline {0.1}A numbered section}{3}{section.0.1}
\contentsline {part}{I\hspace {1em} Introduction: \emph {Test title}.}{7}{part.3}
\contentsline {chapter}{\numberline {1}Inside the part}{9}{chapter.1}
\contentsline {section}{\numberline {1.1}More inside the part}{9}{section.1.1}

我想要链接名为part.1,并指向第 5 页,这是零件标题实际出现的位置:

测试.png

...{5}{part.1}...如果您不使用\toclessand \addcontentsline,那么您在 .toc 文件 () 中会得到什么。

那么,我怎样才能实现

\contentsline {part}{I\hspace {1em} Introduction: \emph {Test title}.}{5}{part.1}

... 自动在 .toc 中,同时拥有编号的所有三个自定义条目\part

答案1

这可能是一个可能的解决方案,通过提供一个\enhancedpart命令,其中包含书签标题的第三个参数。

由于hyperref会自动通过 添加书签\addcontentsline,因此必须将其踢出。该bookmark包提供了一些功能,但必须设置目标键。这是通过使用\hypertarget{...}部件标题自动完成的。(我前段时间发布了一个关于关闭/绕过 此功能的问题\addcontentsline,但到目前为止仍未得到答复 :-(防止 \addcontentsline 中自动 Hy@writebookmark

\documentclass{book}

\usepackage{xcolor}%
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{etoolbox}%

\makeatletter
\newcommand{\enhancedpart@opt}[3][]{%
  \begingroup%
  \renewcommand{\Hy@writebookmark}[5]{}{}{}{}{}% Drop it%
  \phantomsection%
  \part[#1]{\hypertarget{bookmark::\number\value{part}}{}{#2}}
  \bookmark[level=-1,color={blue},dest={bookmark::\number\value{part}}]{#3}%
  \endgroup%
}%

\newcommand{\enhancedpart@noopt}[2]{%
  \enhancedpart[#1]{#1}{#2}%
}%

\newcommand{\enhancedpart}{%
\@ifnextchar[{\enhancedpart@opt}{\enhancedpart@noopt}
}%

\makeatother


\usepackage{hyperref}
\usepackage{bookmark}


% http://stackoverflow.com/questions/2785260/hide-an-entry-from-toc-in-latex
\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[2]{\bgroup\let\addcontentsline=\nocontentsline#1{#2}\egroup}

% copy of hyperref.sty \phantomsection:
%\makeatletter
%\def\phantompart{%
%  \Hy@MakeCurrentHrefAuto{part}%
%  \Hy@raisedlink{\hyper@anchorstart{\@currentHref}\hyper@anchorend}%
%}
%\makeatother


\begin{document}

\tableofcontents

\chapter*{Important notes}

A very important part comes ahead.

\section{A numbered section}

This should show in the TOC, too...


\enhancedpart{Test Title}{Title for bookmark}



Something in this part...

\chapter{Inside the part}

The chapter inside the part...

\section{More inside the part}

The section more inside the part...

\enhancedpart[Another title for the ToC]{A part for the book}{And even another title for the bookmarks}

\end{document}

其他版本的xparse方法

这样,该\enhancedpart命令将起到作用\part[]{}并且不会生成书签条目,或者\part{}[]将使用{}参数作为 Toc 条目,而是[...]作为书签条目。

\documentclass{book}

\usepackage{xcolor}%
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{xparse}

\makeatletter
\NewDocumentCommand{\enhancedpart}{+o+m+o}{%
    \begingroup
    \renewcommand{\Hy@writebookmark}[5]{}{}{}{}{}%
    \phantomsection
    \IfNoValueTF{#3}{%
      \IfNoValueTF{#1}{%
        \part{#2}%
      }{%
        \part[#1]{#2}%
      }%
    }{%
      \IfNoValueTF{#1}{%
        \part{#2}\hypertarget{bookmark::\number\value{part}}{}
        }{%
          \part[#1]{#2}\hypertarget{bookmark::\number\value{part}}{}%
        }%          
      \bookmark[level=-1,color={blue},dest={bookmark::\number\value{part}}]{#3}
    }%
    \endgroup%
  }%
\makeatother

\usepackage[bookmarksnumbered=false]{hyperref}%
\usepackage{bookmark}%


\begin{document}

\tableofcontents

\chapter*{Important notes}

A very important part comes ahead.

\section{A numbered section}

This should show in the TOC, too...


% Toc entry different from main entry, No entry to the bookmarks
\enhancedpart[Test Title for Toc]{Part title}



Something in this part...

\chapter{Inside the part}

The chapter inside the part...

\section{More inside the part}

The section more inside the part...

% Toc entry, main entry, bookmark entry%
\enhancedpart[Another title for the ToC]{A new part for the book}[And even another title for the bookmarks]

% Toc entry the same as main entry and some bookmark%

\enhancedpart{A part for the book}[And even another title for the bookmarks, but the same for the TOC]

% Toc entry and main entry alike, no bookmarks
\enhancedpart{The ultimate part}

\end{document}

答案2

ToC 的末尾会清除页面(双面打印时为两页)。因此,\addcontentsline当 TeX 已经在第 7 页时,正在执行。为了避免这种情况,您可以添加内容行第一的,手动清除页面以确保 ToC 不需要开始新页面:

\documentclass{book}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{hyperref}

% http://stackoverflow.com/questions/2785260/hide-an-entry-from-toc-in-latex
\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[2]{\bgroup\let\addcontentsline\nocontentsline#1{#2}\egroup}

% copy of hyperref.sty \phantomsection:
\makeatletter
\def\phantompart{%
  \Hy@MakeCurrentHrefAuto{part}%
  \Hy@raisedlink{\hyper@anchorstart{\@currentHref}\hyper@anchorend}%
}
\makeatother


\begin{document}

  \tableofcontents

  \chapter*{Important notes}

  A very important part comes ahead.

  \section{A numbered section}

  This should show in the TOC, too...

  \def\ptitle{Test title}

  \cleardoublepage
  \addcontentsline{toc}{part}{\thepart\hspace{1em} Introduction: \emph{\ptitle}.}%
  \tocless\part{%
    \texorpdfstring{%
      Introduction: \emph{\ptitle} - \textbf{and more}. %
    }{%
      Introduction: \ptitle%
    }%
  }

  Something in this part...

  \chapter{Inside the part}

  The chapter inside the part...

  \section{More inside the part}

  The section more inside the part...

\end{document}

目录

答案3

好的,我想我明白了;首先,发现像这样\part- 或者更确切地说\@part- 实际上有一个可选参数:

$ texdef -t latex -c book part -f
\part first defined in "book.cls".

\part:
\long macro:->\if@openright \cleardoublepage \else \clearpage \fi \thispagestyle {plain}\if@twocolumn \onecolumn \@tempswatrue \else \@tempswafalse \fi \null \vfil \secdef \@part \@spart 

$ texdef -t latex -c book @part -f
\@part first defined in "book.cls".

\@part:
macro:[#1]#2->\ifnum \c@secnumdepth >-2\relax \refstepcounter {part}\addcontentsline {toc}{part}{\thepart \hspace {1em}#1}\else \addcontentsline {toc}{part}{#1}\fi \markboth {}{}{\centering \interlinepenalty \@M \normalfont \ifnum \c@secnumdepth >-2\relax \huge \bfseries \partname \nobreakspace \thepart \par \vskip 20\p@ \fi \Huge \bfseries #2\par }\@endpart 

此可选参数专门用于设置目录条目 - 使用\texorpdfstring其中的参数,我们可以控制 PDF 排版目录或 PDF 书签/索引目录。因此,解决方案是在 OP MWE 中更改此部分:

% ...
\def\ptitle{Test title}

% the \part optional argument handles either:
% pdf-typeset TOC (\contentsline), or PDF Bookmark/Index TOC!
\part[%
  \texorpdfstring{%
    Introduction: A \emph{\ptitle}.%
  }{%
    % pdf string for PDF Bookmarks TOC
    Introduction: B \ptitle%
  }%
]{%
  % tex string for \part itself
  Introduction: \emph{\ptitle} - \textbf{and more}. %
}

Something in this part...
% ...

因此,不需要\tocless;也不需要单独的\addcontentsline- 并且在 .toc 文件内部,生成预期的条目:

\contentsline {part}{I\hspace {1em}Introduction: A \emph {Test title}.}{5}{part.1}

...这也意味着目录中显示了正确的页码。

希望就是这样...

相关内容