我偶然发现了一个罕见的臭名昭著的案例\pdfendlink 最终与 \pdfstartlink 处于不同的嵌套级别错误在最新的系统(Ubuntu 14.10,6.83m hyperref
)上。如果全部满足以下条件:
- 双列模式
- 当链接跨越两个页面时
- 当链接的起点与同一页面上的图形跨越两列时。
请注意,对于不跨一页但跨两行的链接,natbib 和 hyperref 的(作者,年份)样式产生两个链接(正确)。该问题仅发生在页面边界。此外,该问题不会发生在单列模式下(请参阅修改示例)。这个数字似乎也是必要的(见另一个修改的例子)。
在开发文档期间,解决此问题的最佳方法是什么?(我发现可点击的链接很有用,而且我现在也更喜欢坚持使用双列模式。)从hyperref
技术上讲可以修复吗?
这可以看作是其中之一错误报告问题。虽然我知道这一点,但解决方法可能仍然有用有限的修复传播到 Ubuntu LTS 所需的时间(可能长达四年,对某些人来说是永恒)。因此,它可能对文档目的有用;如果不合适,请随时关闭。
MWE(也在 GitHub 上)
...对我来说最小但不幸的是并不小,并且使用btxdoc.bib
来自natbib
。
\documentclass[a5paper,twocolumn]{scrartcl}
\pagestyle{empty}
% Fatal combination
\usepackage{natbib,hyperref}
% For constructing the MWE
\usepackage{mwe,lipsum}
\bibliographystyle{chicago}
\begin{document}
\begin{figure*}[t]
\includegraphics[width=\textwidth]{example-image-golden}
\end{figure*}
\lipsum[1]
\lipsum[1]
\lipsum[2]
Test line break:
\citep{strunk-and-white}
Works for first word.
\citep{strunk-and-white}
And for second.
Conclusion: Line breaks work well.
Now what happens if we force the break at the page boundary?
Let's take a look
We make this just long enough to break the link at page boundary
\citep{strunk-and-white}
\bibliography{btxdoc}
\end{document}
错误信息
! pdfTeX error (ext4): \pdfendlink ended up in different nesting level than \pd
fstartlink.
\AtBegShi@Output ...ipout \box \AtBeginShipoutBox
\fi \fi
l.33 \end{document}
输出
(第 2 页)稍作修改的非破坏性示例:
答案1
横跨两列的浮动对象 ( ) 是这里的罪魁祸首,因为它在包含打开引用超链接figure*
的输出页面中引入了额外的装箱级别。\pdfstartlink
接下来的页面是“正常”的双列页面,没有浮动,因此结尾\pdfendlink
处有一个少一级的框。
为了解决这个问题,我们可以为有问题的 增加一个装箱级别\pdfendlink
。为此,下面的示例定义了
\addOneNestingLevelEndLink
它被插入到有问题的命令之前\citep
。
也可能出现相反的情况,即在引用超链接结束的页面上放置两列浮动。此时, \pdfstartlink
必须增加命令的装箱级别。因此,
\addOneNestingLevelStartLink ,
同样,要放在相关引用命令的前面。可以一次使用其中一个命令。
示例(分享LaTeX):
\documentclass[a5paper,twocolumn]{scrartcl}
\usepackage{filecontents}
\begin{filecontents}{btxdoc.bib}
@BOOK{strunk-and-white,
author = "Strunk, Jr., William and E. B. White",
title = "The Elements of Style",
publisher = "Macmillan",
edition = "Third",
year = 1979 }
\end{filecontents}
\pagestyle{empty}
\usepackage{natbib}
\usepackage[colorlinks,citecolor=blue]{hyperref}
% For constructing the MWE
\usepackage{mwe,lipsum}
\bibliographystyle{chicago}
\makeatletter\ifdefined\Hy@StartlinkName
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \addOneNestingLevelStartLink
% \addOneNestingLevelEndLink
%
% put ONE of \addOneNestingLevel(Start|End)Link in front of offending \cite
% depending on the placement of the double-column float object
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\addOneNestingLevelStartLink{%
\gdef\Hy@StartlinkName##1##2{%
\sbox0{\Hy@StartlinkNameOrig{##1}{##2}}\usebox0
\global\let\Hy@StartlinkName\Hy@StartlinkNameOrig%
}%
}
\def\addOneNestingLevelEndLink{%
\gdef\pdfendlink{%
\sbox0{\pdfendlinkOrig}\usebox0%
\global\let\pdfendlink\pdfendlinkOrig%
}%
}
\let\Hy@StartlinkNameOrig\Hy@StartlinkName
\let\pdfendlinkOrig\pdfendlink
\else
\let\addOneNestingLevelStartLink\relax
\let\addOneNestingLevelEndLink\relax
\fi
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatother
\begin{document}
\begin{figure*}[t]
\includegraphics[width=\textwidth]{example-image-golden}
\end{figure*}
\lipsum[1]
\lipsum[1]
\lipsum[2]
Test line break:
\citep{strunk-and-white}
Works for first word.
\citep{strunk-and-white}
And for second.
Conclusion: Line breaks work well.
Now what happens if we force the break at the page boundary?
Let's take a look
We make this just long enough to break the link at page boundary
\addOneNestingLevelEndLink\citep{strunk-and-white}
\bibliography{btxdoc}
\end{document}
答案2
在文档开发过程中,解决这个问题的好办法是什么?(我发现可点击的链接很有用,而且我现在更喜欢坚持使用双列模式。)从技术上讲,可以修复 hyperref 吗?
我在这里找到了这个解决方法,至少在文档仍在处理时有效:https://binhngq.blogspot.de/2015/11/pdfendlink-ended-up-in-different.html
只需输入
\hypersetup{draft}
加载 hyperref 包后。这会使您的文档编译,但链接不起作用。这样您就不会在多个中间阶段遇到问题。我的文档遇到了这个问题,无法编译文档的中间阶段真的很烦人。最终版本在没有解决方法的情况下运行良好。如果您的最终版本恰好有这个问题,并且您希望它有链接,那么不幸的是这无济于事。