latex3 / hyperref

Hypertext support for LaTeX
165 stars 35 forks source link

[xr-hyper] decouple \externaldocument from hyperref loading state #259

Closed mrpiggi closed 10 months ago

mrpiggi commented 1 year ago

As I did not find anything on the issue tracker here, I am wondering, if I do anything wrong... Using this MWE, I get warnings both with pdflatex pdfTeX warning (dest): name{section.1} has been referenced but does not exist, replaced by a fixed one as well as lualatex warning (pdf backend): unreferenced destination with name 'section.1' regardless if a prefix with \externaldocument is used or not.

\begin{filecontents}{external.tex}
\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{A\label{extlbl}}
\end{document}
\end{filecontents}

\documentclass{article}
\usepackage{xr-hyper}
\externaldocument[ext-]{external}
\usepackage{hyperref}
\begin{document}
\ref{ext-extlbl}
\end{document}
u-fischer commented 1 year ago

Move \externaldocument[ext-]{external} behind hyperref. hyperref redefines some commands of xr-hyper so that it now stores the file name:

\begin{filecontents}{externalA.tex}
\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{A\label{extlbl}}
\end{document}
\end{filecontents}
\begin{filecontents}{externalB.tex}
\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{A\label{extlbl}}
\end{document}
\end{filecontents}

\documentclass{article}
\usepackage{xr-hyper}
\externaldocument[extA-]{externalA}

\usepackage{hyperref}

\externaldocument[extB-]{externalB}
\ExplSyntaxOn
\tl_show:c{r@extA-extlbl}
\tl_show:c{r@extB-extlbl}
\ExplSyntaxOff

\begin{document}

\ref{extA-extlbl}
\quad
\ref{extB-extlbl}

\end{document}

gives

> \r@extA-extlbl={1}{1}{A}{section.1}{}.

> \r@extB-extlbl={1}{1}{A}{section.1}{externalB.pdf}.
mrpiggi commented 1 year ago

Thanks for the immediate reply and the suggested solution. Would it make sense to use a hook within \XR@@ in order to execute it again after hyperref was loaded or delay it's execution at all after hyperref. This would improve usability a lot.

\begin{filecontents}{externalA.tex}
\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{A\label{extlbl}}
\end{document}
\end{filecontents}
\begin{filecontents}{externalB.tex}
\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{A\label{extlbl}}
\end{document}
\end{filecontents}

\documentclass{article}
\usepackage{xr-hyper}
\makeatletter
\def\XR@@#1#2#3[#4]{%
  \@ifpackageloaded{hyperref}{}%
    {\AddToHook{package/hyperref/after}{\XR@@{#1}{#2}{#3}[#4]}}%
  {%
  \makeatletter
  \def\XR@prefix{#1}%
   \def\XR@nocite{#2}%
   \ifx\XR@nocite\XR@@nocite
     \let\XR@bibcite\vadjust
   \else
     \let\XR@bibcite\bibcite
   \fi
  \def\XR@URL{#4}%
  \filename@parse{#3}%
  \XR@next#3.aux\relax\\}}
\makeatother
\externaldocument[extA-]{externalA}

\usepackage{hyperref}

\externaldocument[extB-]{externalB}
\ExplSyntaxOn
\tl_show:c{r@extA-extlbl}
\tl_show:c{r@extB-extlbl}
\ExplSyntaxOff

\begin{document}

\ref{extA-extlbl}
\quad
\ref{extB-extlbl}

\end{document}
u-fischer commented 1 year ago

I don't think that this is the right solution. Imho the method used currently by hyperref / xr-hyper to decide if an internal or an external link should be created is flawed. hyperref tests if the fifth argument is empty and this means that external.tex can not simply fill this argument as it would harm its own internal links and xr-hyper has to postprocess the label definitions to smuggle the data in. It would be better if xr-hyper would create some command, e.g. XR@gotor@\XR@prefix<label> with the url info. Then hyperref could test for that, and users would have better options to configure the links. And if would free the fifth argument for better uses.

mrpiggi commented 1 year ago

Well, then this is probably another item on your already well-filled to-do list. Anyway, from a user's point of view, it should not matter whether \externaldocument is used before or after loading the hyperref package.

u-fischer commented 10 months ago

This should now work. The file name is always stored, regardless if and when hyperref is loaded.

muzimuzhi commented 10 months ago

Corresponding commit is c50689b (xr-hyper: always store url/file name, 2023-11-26).