本文已加入專欄文章目錄,歸入「進階使用」文章系列。

本文涉及的宏包

  • hyperref
  • bookmark,生成 PDF 書籤,依賴 hyperref
  • tocbibind,為目錄、參考文獻和索引生成目錄項

默認情況

章節命令(以 section 為例)

section [<short title>]{<long title>}
section*[<short title>]{<long title>}

分別生成編號和不編號的章節標題。默認情況下,

  • 編號的章節標題,產生目錄項,即在 ableofcontents 生成的目錄中有對應的條目。
  • 不編號的章節標題,不產生目錄項。

如果使用 hyperref/bookmark 宏包來生成 PDF 書籤,那麼

  • 編號的章節標題,還產生 PDF 書籤。點擊標題對應的書籤和目錄項,將跳轉到正文中章節標題出現的位置。
  • 不編號的章節標題,不產生 PDF 書籤。

不編號章節舉例

以書籍舉例,序言、前言、參考文獻和索引部分的標題,是常見的不編號章節標題。特別地,由 ableofcontents 產生的目錄部分的標題,也是不編號的章節標題。

這些不編號章節,按生成方式,又有兩類

  • 手動生成的,例如 section*{前言}
  • 自動生成的,例如命令 ableofcontentsprintindex就會自動生成目錄和索引部分的標題。這些命令的內部,也使用了帶星號的章節命令,如 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 是其中的一個。(暫不清楚 HyperGlobalCurrentHrefHyperLocalCurrentHref@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ε 格式:計數器》有所提及)有相似之處。


推薦閱讀:
相关文章