我一直在使用书签包为我的论文添加自定义 PDF 书签。更具体地说,我开始使用这个包是因为我不想让 ToC、LoF 和 LoT 出现在 ToC 中,但仍出现在书签栏中。
我遇到的问题是,hypertarget
不指向目标部分第一页的顶部,而是指向其上方的某个位置。结果是,随着 ToC、LoF 和 LoT 越来越长,超目标越来越“偏离目标”。
下面是我一直在使用的代码的 MWE:
\documentclass[12pt,a4paper]{book}
\usepackage[numbered]{bookmark}
\usepackage{hyperref}
\usepackage[nottoc, notlof, notlot,chapter]{tocbibind}
\begin{document}
\frontmatter
\hypertarget{tocpage}{}
\tableofcontents
\bookmark[dest=tocpage]{Table of Contents}
\hypertarget{lofpage}{}
\listoffigures
\bookmark[dest=lofpage]{List of Figures}
\hypertarget{lotpage}{}
\listoftables
\bookmark[dest=lotpage]{List of Tables}
\mainmatter
\chapter{Chapter 1}
\section{Section 1.1}
\subsection{Subsection 1.1.1}
\begin{figure}[h]
\LARGE A
\caption{A figure}
\end{figure}
\subsection{Subsection 1.1.2}
\section{Section 1.2}
\subsection{Subsection 1.2.1}
\subsection{Subsection 1.2.2}
\chapter{Chapter 2}
\section{Section 2.1}
\begin{table}[h]
\caption{A table}
\end{table}
\subsection{Subsection 2.1.1}
\subsection{Subsection 2.1.2}
\section{Section 2.2}
\subsection{Subsection 2.2.1}
\subsection{Subsection 2.2.2}
\endmatter
\end{document}
更新 我想到的解决方案的行为与我所假设的章节和小节的默认超引用行为类似:超目标指向标题,而不管标题位于文本中的什么位置。
我尝试使用 etoolbox 包和命令在序言中添加以下内容\apptocmd
。
\usepackage{etoolbox}
\makeatletter
\AtBeginDocument{%
\apptocmd{\contentsname}{\hypertarget{tocpage}{}}{}{}
}
\makeatother
当然,我注释掉了\hypertarget{tocpage}
MWE中现有的内容。
当我使用此代码运行 MWE 时,出现以下错误:
[1]./Thesis.toc !Missing control sequence inserted <inserted text> \inaccessible.
对于我在命令定义中做错什么,您有什么想法吗?
答案1
开始listsof
新的一页后 hypertarget
已选择目标页面。解决此问题的一种方法是在之前插入\cleardoublepage
或:clearpage
hypertarget
\cleardoublepage
\hypertarget{lofpage}{}
\listoffigures
\bookmark[dest=lofpage]{List of Figures}
当然,如果您要使用memoir
文档类,则可以使用\clearforchapter
,它更具语义,并且可以自动调整单侧/双面。
答案2
hyperref
\hypertarget
自动定义与您尝试插入的 s等同的内容,并且已位于正确的位置。在 之后\chapter*
,紧接在前的锚点的名称存储在 中\@currentHref
。因此,在您的\bookmark
命令中,您只需要引用\@currentHref
(使用\makeatletter
active 或 via \csname @currentHref\endcsname
)。在这里,我在序言中定义了一个宏,以免在文档正文中\bookmarkCurrentHref
使用:@
\documentclass[12pt,a4paper]{book}
\usepackage[numbered]{bookmark}
\usepackage{hyperref}
\usepackage[nottoc, notlof, notlot,chapter]{tocbibind}
\makeatletter
\newcommand*{\bookmarkCurrentHref}[1][]{\bookmark[dest=\@currentHref,#1]}
\makeatother
\begin{document}
\frontmatter
\tableofcontents
\bookmarkCurrentHref{Table of Contents}
\makeatletter
\listoffigures
\bookmarkCurrentHref{List of Figures}
\listoftables
\bookmarkCurrentHref{List of Tables}
\mainmatter
\chapter{Chapter 1}
\section{Section 1.1}
\subsection{Subsection 1.1.1}
\begin{figure}[h]
\LARGE A
\caption{A figure}
\end{figure}
\subsection{Subsection 1.1.2}
\section{Section 1.2}
\subsection{Subsection 1.2.1}
\subsection{Subsection 1.2.2}
\chapter{Chapter 2}
\section{Section 2.1}
\begin{table}[h]
\caption{A table}
\end{table}
\subsection{Subsection 2.1.1}
\subsection{Subsection 2.1.2}
\section{Section 2.2}
\subsection{Subsection 2.2.1}
\subsection{Subsection 2.2.2}
%\endmatter
\backmatter
\end{document}
除了为您的问题提供解决方案之外,我还会尝试解释为什么您的尝试没有成功(请注意,此处的任何代码仅作为解释提供,我强烈建议使用上述方法而不是此处的任何方法):
您的补丁会
\contentsname
导致问题,因为该宏被多次使用。具体来说,它用于设置章节名称并传递给。这是您的 MWE 中有效的\@mkboth
的定义,在之后显示:\tableofcontents
\show\tableofcontents
\begin{document}
\if@twocolumn \@restonecoltrue \onecolumn \else \@restonecolfalse \fi \chapter *{\contentsname \@mkboth {\MakeUppercase \contentsname }{\MakeUppercase \contentsname }}\@starttoc {toc}\if@restonecol \twocolumn \fi
如果您手动重新定义
\tableofcontents
以便只有第一个\contentsname
受到影响,它就会按预期工作:\def\tableofcontents{\if@twocolumn \@restonecoltrue \onecolumn \else \@restonecolfalse \fi \chapter *{\hypertarget{tocpage}{}\contentsname \@mkboth {\MakeUppercase \contentsname }{\MakeUppercase \contentsname }}\@starttoc {toc}\if@restonecol \twocolumn \fi}
(请注意,这需要用
\makeatletter
...括起来\makeatother
。)用 来修补这个问题
etoolbox
并不会完全是琐碎/最小的,因为\@mkboth
也是 参数的一部分\chapter*
。对于
\listoffigures
和也类似\listoftables
,只是在这些情况\@mkboth
下不是参数的一部分,\chapter*
这使得它们更容易修补,例如(尽管再次强调,我不建议您这样做):\patchcmd{\listoffigures}{\chapter *{\listfigurename }}{\chapter*{\hypertarget{lofpage}{}\listfigurename}}{}{\errmessage{failed to patch}}
(请注意,这不需要用
\makeatletter
...包围\makeatother
。)