2

I used the answer here to help me create a document where numbering for theorems and the like appears on the left. But I would like to be able to reference and hyperlink back to these theorems/definitions/etc in my document. When I added hyperref and clicked on the links, they both sent me back to the front page. (I created a newpage in the code below to make the issue clearer, and I changed the documentclass from article to book since that is what I am using. The issue persists in either case.)

Any ideas to get the hyperlinks working correctly?

\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}
Jessica
  • 97
  • 1
    If you try hyperref with the answer I gave to your other similar question, you'll see it works out of the box. – egreg Jul 23 '18 at 20:33

1 Answers1

2

I observe exactly the same problem you observe.

Besides the fact that clicking hyperlinks yields navigating to the front page instead of the location where the referenced theorem-thingie can be found, I observed that the .log-file contains warnings:

pdfTeX warning (dest): name{fctaylor@thm.0.1.1} has been referenced but does no
t exist, replaced by a fixed one

pdfTeX warning (dest): name{fctaylor@thm.0.1.2} has been referenced but does no
t exist, replaced by a fixed one

I think playing around with \phantomsection is not the best approach at solving that problem as \phantomsection would, e.g., break the \autoref-feature for your thm-environments.

The problem is:

Theorem-like environments usually put their label-phrases into a box-register whose name is \@labels and rely on \everypar for placing that box/the content of that box-register into the output-file. The hyperref-package causes that at the time of putting the label-phrase into the box-register, also the name of a new anchor for hyperlinks gets created. The hyperref-package also causes placing the anchor when—due to \everypar—that box gets placed.

In your unusual case both that box and the anchor do never get placed because the thm-environment does have another nesting-level where the label is typeset within the optional argument of an \item of the fctayloritemize-environment, while the LaTeX 2ε-kernel-macro \@item which does underlie \item does override both the \@labels-box and the\everypar-hook with things/instructions which do not refer to placing an anchor with the name in question into the output-file. Thus you have an anchor-name for \label-commands but no suitable anchor when carrying out a command like \ref which also does attempt to create a link to the corresponding anchor.

When the TeX-engine (pdflatex or whatever) finds itself attempting to produce a link to a non existing anchor/destination, it will issue a warning-message which will also occur in the .log-file and will link to a "dummy-destination/dummy-anchor" on the first page of the document.

While the name for the anchor is already created by the surrounding-theorem-environment, you need to pass directives for placing the anchor into the optional argument of that \list-item as well:

\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}

Seems with these modifications you don't get warnings into the .log file and hyperlinks link to correct destinations/anchors.

Ulrich Diez
  • 28,770