[LaTeX] 把不编号章节加进目录和 PDF 书签
本文已加入专栏文章目录,归入「进阶使用」文章系列。
本文涉及的宏包
hyperref
bookmark
,生成 PDF 书签,依赖hyperref
tocbibind
,为目录、参考文献和索引生成目录项
默认情况
章节命令(以 section
为例)
section [<short title>]{<long title>}
section*[<short title>]{<long title>}
分别生成编号和不编号的章节标题。默认情况下,
- 编号的章节标题,产生目录项,即在
ableofcontents
生成的目录中有对应的条目。 - 不编号的章节标题,不产生目录项。
如果使用 hyperref
/bookmark
宏包来生成 PDF 书签,那么
- 编号的章节标题,还产生 PDF 书签。点击标题对应的书签和目录项,将跳转到正文中章节标题出现的位置。
- 不编号的章节标题,不产生 PDF 书签。
不编号章节举例
以书籍举例,序言、前言、参考文献和索引部分的标题,是常见的不编号章节标题。特别地,由 ableofcontents
产生的目录部分的标题,也是不编号的章节标题。
这些不编号章节,按生成方式,又有两类
- 手动生成的,例如
section*{前言}
- 自动生成的,例如命令
ableofcontents
和printindex
就会自动生成目录和索引部分的标题。这些命令的内部,也使用了带星号的章节命令,如section*{...}
。
把不编号章节同时加入目录和 PDF 书签
手动生成的
section*{前言}
addcontentsline{toc}{section}{前言}
addcontentsline
必须出现在章节标题命令之后。
自动生成的
- 理论上,需要用户了解并修改
ableofcontents
命令的定义,往里加入addcontentsline
或类似命令。 - 实际上,已有宏包替用户做了这类事,例如
tocbibind
宏包就提供了把目录(toc
)、参考文献(bib
)和索引(ind
)的标题加入目录的功能。载入宏包,功能即生效。宏包文档介绍了一些可配置项,例如只把索引加入目录,而另两项不动。 - 注意,
tocbibind
宏包重定义了相关命令(如ableofcontents
),如有其他宏包和文档类修改了相同命令,可能遇到兼容性问题。
注意,把不编号章节加入目录时,对应的 PDF 书签会自动添加。每一条目录项都有对应的 PDF 书签,这是合理的默认行为。
把不编号章节仅加入 PDF 书签
手动生成的
% preamble
% usepackage{bookmark}
section*{title 2}
% see definition of Hy@MakeCurrentHref in hyperref.sty
ookmark[dest=HyperLocalCurrentHref, level=1]{title 2}
说明
- 类似地,
ookmark
需要在章节标题命令之后使用。 dest
选项接受一个由hyperref
定义的超链接目标(destination)- 带星号的章节标题命令(如
section*
)会创建一个新的超链接目标,并将其储存在一系列命令中,HyperLocalCurrentHref
是其中的一个。(暂不清楚HyperGlobalCurrentHref
、HyperLocalCurrentHref
和@currentHref
在应用上的差异。) level
选项接受一个整数,用于表示书签的(绝对)层级。类似的还有接受相对层级的rellevel
选项,详见bookmark
宏包文档 1.2.5 节。
自动生成的
- 理论上,同样需要用户了解并修改相应命令的定义。
- 实际上,笔者还没发现提供相关功能的宏包。
不推荐的用法
只用 hyperref
宏包实现「把手动生成的不编号章节仅加入 PDF 书签」,生成的书签跳转目标「不准」,需要做额外的调整。见本专栏之前的文章《(旧文)[LaTeX] - 使手动添加的 PDF 章节书签跳转到准确位置》。使用bookmark
宏包则没有这个问题。
在 hyperref
的用户文档中,针对 PDF 书签的功能,也推荐用户使用 bookmark
宏包(见 hyperref
文档 4.1.1 节末尾)。
所以,涉及手动生成 PDF 书签时,推荐 bookmark
宏包。
比较完整的例子
下面的例子,集中展示了前文提到的几种用法。
documentclass{article}
usepackage{lipsum}
usepackage{tocbibind}
usepackage[bookmarksopen=true]{hyperref}
usepackage{bookmark}
egin{document}
ableofcontents
section{abc}
lipsum
section{bcd}
lipsum
section*{title}
addcontentsline{toc}{section}{title}
subsection*{sub title}
addcontentsline{toc}{subsection}{sub title}
subsection*{sub title 2}
addcontentsline{toc}{subsection}{sub title 2}
lipsum
section*{title 2}
% see definition of Hy@MakeCurrentHref in hyperref.sty
ookmark[dest=HyperLocalCurrentHref, level=1]{title 2}
lipsum
end{document}
附记
一条不带有链接跳转的目录项,它所需的只有三项信息(详见本专栏文章《探索 LaTeX2e 格式:目录项(外一篇:怎么改 numwidth)》),
- 层级
- 内容(包括编号和文本)
- 页码
所以,更一般的情况下,addcontentsline
只需和对应的无编号章节目录出现在同一页,保证两者的页码相同即可。
一条带有链接跳转的目录项,它需要额外获取跳转目标的信息。PDF 格式支持的跳转目标,可以储存三项内容,
- 目标所在页面(以绝对页码的形式)
- 目标在那一页的横纵相对位置
- 跳转后的显示状态(如适应宽度、适应高度等)
详见 PDF Ref v1.7, Sec. 8.2.1。在 hyperref
里,跳转目标储存在 @currentHref
。 所以,更一般的情况下,只需保证在无编号章节目录和 ookmark
命令之间,@currentHref
储存的信息不被刷新即可。
@currentHref
这个宏的命名方式,和 LaTeX2e 中储存标签信息的内部宏 @currentlabel
(本专栏文章《探索 LaTeX2ε 格式:计数器》有所提及)有相似之处。
推荐阅读: