![指向自定义定理的超链接不准确](https://linux22.com/image/379646/%E6%8C%87%E5%90%91%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AE%9A%E7%90%86%E7%9A%84%E8%B6%85%E9%93%BE%E6%8E%A5%E4%B8%8D%E5%87%86%E7%A1%AE.png)
我用了答案这里帮助我创建一个文档,其中定理和类似内容的编号出现在左边。但我希望能够在我的文档中引用并超链接回这些定理/定义/等等。当我添加hyperref
并单击链接时,它们都会将我送回首页。(我newpage
在下面的代码中创建了一个以使问题更清晰,并且我将从更改documentclass
为article
因为book
我正在使用。无论哪种情况,问题仍然存在。)
有什么想法可以让超链接正常工作吗?
\documentclass{book}
\usepackage{showframe} % just for the example
\usepackage{amsthm}
\usepackage{enumitem}
\usepackage{xparse}
\usepackage{hyperref}
\usepackage{lipsum}
\newtheoremstyle{fctaylor}% name
{\topsep}% Space above
{\topsep}% Space below
{\normalfont}% Body font
{}% Indent amount (empty = no indent, \parindent = para indent)
{\bfseries}% Thm head font
{}% Punctuation after thm head
{0pt}% Space after thm head: " " = normal interword space;
{\makethmhead{#1}{#2}{#3}}
\newlength\fctaylortheoremindent
\AtBeginDocument{\setlength\fctaylortheoremindent{3em}} % <- customize here
\newlength\fctaylorlabelsep
\AtBeginDocument{\setlength\fctaylorlabelsep{1em}} % <- customize here
\makeatletter
\newcommand{\makethmhead}[3]{%
\gdef\thisthmhead{%
\makebox[\fctaylortheoremindent][l]{\bfseries#2}%
{\bfseries#1}%
\@ifnotempty{#3}{ (#3)}%
\hspace{\fctaylorlabelsep}%
}%
}
\makeatother
\newenvironment{fctayloritemize}
{\list{}{%
\leftmargin=\fctaylortheoremindent
\labelwidth=\dimexpr\fctaylortheoremindent-\labelsep\relax
\itemindent=0pt
}}
{\endlist}
\NewDocumentCommand{\newfctaylortheorem}{smomo}{%
\IfBooleanTF{#1}
{\newtheorem*{fctaylor@#2}{#4}}
{\IfNoValueTF{#3}
{\IfNoValueTF{#5}
{\newtheorem{fctaylor@#2}{#4}}
{\newtheorem{fctaylor@#2}{#4}[#5]}}
{\newtheorem{fctaylor@#2}[fctaylor@#3]{#4}}}%
\NewDocumentEnvironment{#2}{o}
{\IfNoValueTF{##1}{\begin{fctaylor@#2}}{\begin{fctaylor@#2}[##1]}%
\begin{fctayloritemize}\item[\thisthmhead\hfill]}
{\end{fctayloritemize}\end{fctaylor@#2}}%
}
\theoremstyle{fctaylor}
\newfctaylortheorem{thm}{Theorem}[section]
\newfctaylortheorem*{defn}{Definition}
\begin{document}
\section{One}
\begin{defn}
\lipsum*[2]
\end{defn}
\newpage
\begin{thm}\label{A}
\lipsum*[2]
\end{thm}
\begin{thm}[Somebody]\label{B}
Something that should show how the text is split across line boundaries
and is correctly indented. And some equivalent conditions:
\begin{enumerate}[label=\upshape(\alph*),ref=(\alph*)]
\item a condition
\item another
\item and another
\end{enumerate}
which show the point made.
\end{thm}
\newpage
Here are the references: \ref{A} and \ref{B}.
\end{document}
答案1
我观察到的问题和您观察到的问题完全相同。
除了单击超链接会导航到首页而不是可以找到所引用的定理的位置之外,我还发现 .log 文件包含警告:
pdfTeX warning (dest): name{[email protected]} has been referenced but does no
t exist, replaced by a fixed one
pdfTeX warning (dest): name{[email protected]} has been referenced but does no
t exist, replaced by a fixed one
我认为,玩弄这种\phantomsection
方法并不是解决该问题的最佳方法\phantomsection
,因为这样可能会破坏\autoref
您的thm
环境的功能。
问题是:
定理类环境通常将其标签短语放入名为的盒子寄存器中,\@labels
并依赖于\everypar
将该盒子/该盒子寄存器的内容放入输出文件中。超链接-package 导致在将标签短语放入框寄存器时,还会创建一个新的超链接锚点的名称。超链接-package 也会导致在由于\everypar
该盒子被放置时放置锚点。
在您这种不寻常的情况下,该框和锚点都永远不会被放置,因为 -environmentthm
确实有另一个嵌套级别,其中标签在 -environment 的可选参数中排版\item
,fctayloritemize
而底层的 LaTeX 2ε-kernel-macro\@item
会使用不涉及\item
将具有相关名称的锚点放入输出文件中的内容/指令覆盖 -box\@labels
和\everypar
-hook。因此,您有一个用于 -commands 的锚点名称\label
,但在执行类似命令时没有合适的锚点,\ref
该命令也会尝试创建指向相应锚点的链接。
当 TeX 引擎(pdflatex 或其他)发现自己试图生成指向不存在的锚点/目标的链接时,它将发出一条警告消息,该消息也会出现在 .log 文件中,并链接到文档第一页上的“虚拟目标/虚拟锚点”。
虽然锚点的名称已经由周围的定理环境创建,但您仍然需要传递将锚点放入该 \list-item 的可选参数中的指令:
\documentclass{book}
\usepackage{showframe} % just for the example
\usepackage{amsthm}
\usepackage{enumitem}
\usepackage{xparse}
\usepackage{hyperref}
\usepackage{lipsum}
\newtheoremstyle{fctaylor}% name
{\topsep}% Space above
{\topsep}% Space below
{\normalfont}% Body font
{}% Indent amount (empty = no indent, \parindent = para indent)
{\bfseries}% Thm head font
{}% Punctuation after thm head
{0pt}% Space after thm head: " " = normal interword space;
{\makethmhead{#1}{#2}{#3}}
\newlength\fctaylortheoremindent
\AtBeginDocument{\setlength\fctaylortheoremindent{3em}} % <- customize here
\newlength\fctaylorlabelsep
\AtBeginDocument{\setlength\fctaylorlabelsep{1em}} % <- customize here
\makeatletter
\newcommand{\makethmhead}[3]{%
\gdef\thisthmhead{%
\makebox[\fctaylortheoremindent][l]{\bfseries#2}%
{\bfseries#1}%
\@ifnotempty{#3}{ (#3)}%
\hspace{\fctaylorlabelsep}%
}%
}
\makeatother
\newenvironment{fctayloritemize}
{\list{}{%
\leftmargin=\fctaylortheoremindent
\labelwidth=\dimexpr\fctaylortheoremindent-\labelsep\relax
\itemindent=0pt
}}
{\endlist}
\makeatletter
\NewDocumentCommand{\newfctaylortheorem}{smomo}{%
\IfBooleanTF{#1}
{\newtheorem*{fctaylor@#2}{#4}}
{\IfNoValueTF{#3}
{\IfNoValueTF{#5}
{\newtheorem{fctaylor@#2}{#4}}
{\newtheorem{fctaylor@#2}{#4}[#5]}}
{\newtheorem{fctaylor@#2}[fctaylor@#3]{#4}}}%
%
% Create the macro holding the textual phrase for `\autoref`:
% Be aware that this only works when the theorem in question dose not
% share its counter with an other theorem-like environment defined
% previously.
\IfBooleanTF{#1}{}{%%
\expandafter\newcommand\csname fctaylor@#2autorefname\endcsname{#4}%
}%
%
\NewDocumentEnvironment{#2}{o}
{\IfNoValueTF{##1}{\begin{fctaylor@#2}}{\begin{fctaylor@#2}[##1]}%
\begin{fctayloritemize}\item[{%
% Also pass instructions for placing an anchor.
% The name of the anchor was already created by the
% fctaylor@#2-environment and saved either in the nacro
% \@currentHref or in the macro \Hy@dth@currentHref:
% In case there is a counter, its name is saved in
% \dth@counter, otherwise \dth@counter expands to emptiness.
\ifx\@empty\dth@counter\else
\Hy@raisedlink{%
\hyper@anchorstart{%
\ltx@ifundefined{Hy@dth@currentHref}%
\@currentHref\Hy@dth@currentHref
}\hyper@anchorend
}%
\fi
\thisthmhead\hfill}]}
{\end{fctayloritemize}\end{fctaylor@#2}}%
}
\makeatother
\theoremstyle{fctaylor}
\newfctaylortheorem{thm}{Theorem}[section]
\newfctaylortheorem*{defn}{Definition}
\begin{document}
\section{One}
\begin{defn}
\lipsum*[2]
\end{defn}
\newpage
\begin{thm}\label{A}
\lipsum*[2]
\end{thm}
\begin{thm}[Somebody]\label{B}
Something that should show how the text is split across line boundaries
and is correctly indented. And some equivalent conditions:
\begin{enumerate}[label=\upshape(\alph*),ref=(\alph*)]
\item a condition
\item another
\item and another
\end{enumerate}
which show the point made.
\end{thm}
\newpage
Here are the references: \ref{A} and \ref{B}
and \autoref{A} and \autoref{B}
\end{document}
似乎通过这些修改,您不会在 .log 文件中收到警告,并且超链接会链接到正确的目的地/锚点。