12

I am using a combination of xr-hyper, hyperref and cleveref with multiple files. Old code that I have is no longer working correctly. The external references now include the file name of the extrenal file, rather just the referenced number.

In the example below, I compile fileone first, and then filetwo, which refers to the section in fileone. The output of filetwo is then

enter image description here

instead of just Section 1.

fileone.tex

\documentclass{article}

\usepackage{xr-hyper} \usepackage{hyperref} \usepackage{cleveref}

\begin{document}

\section{One} \label{sec:one}

\end{document}

filetwo.tex

\documentclass{article}

\usepackage{xr-hyper} \usepackage{hyperref} \usepackage{cleveref}

\externaldocument{fileone}

\begin{document}

\Cref{sec:one}

\end{document}

I suspect some fix to cleveref is needed, but have not tracked down exactly what is needed.

For reference the file versions are

xr-hyper.sty    2024-01-20 v7.01h eXternal References (DPC)
hyperref.sty    2024-01-20 v7.01h Hypertext links for LaTeX
cleveref.sty    2018/03/27 v0.21.4 Intelligent cross-referencing
Andrew Swann
  • 95,762

1 Answers1

16

Edit 2023-03-28

A firstaid for cleveref has been added to LaTeX which contains the redefinitions mentioned in the answer. With the next LaTeX release and with the latex-dev released today the references will be correct again.

Old Answer

In a current LaTeX, the syntax of \newlabel in the .aux file has been unified with the syntax used by hyperref and always contains five data containers. cleveref has not been adapted to this change and still only uses two data container in its definition. So your external .aux file contains (I added some spaces for better visibility):

\newlabel{sec:one}{  {1}  {1}  {One}  {section.1}  {}  }    %<------- five
\newlabel{sec:one@cref}{  {[section][1][]1}  {[1][1][]1}  } %<------- two

Inside a document it doesn't matter so much that the cleveref label has only two data container, as cleveref is the only one using it. But xr-hyper tries to adhere to the new standard too and extends every label it reads to five data container. It also makes use of the fifth data container to store the file name for links.

Now, recently xr-hyper has been extended to store always the file name (and not only if the label contains a destination name in the fourth container) to allow file links to the external document even if that document didn't use hyperref. With this change one gets this definitions for the labels from the external document:

> \r@sec:one=macro:
->{1}{1}{One}{section.1}{fileone.pdf}.

> \r@sec:one@cref=macro: ->{[section][1][]1}{[1][1][]1}{}{}{fileone.pdf}. % would be in older versions: % ->{[section][1][]1}{[1][1][]1}{}{}{}.

And then cleveref falls over the fileone.pdf in the last argument.

The best would be if cleveref would be updated to use the standard five data container always too, so that everything is in sync. For now, you can do something like this:

\documentclass{article}

\usepackage{xr-hyper} \usepackage{hyperref} \usepackage{cleveref}

\externaldocument{fileone}

\makeatletter \def\cref@getref#1#2{% \expandafter\let\expandafter#2\csname r@#1@cref\endcsname% \expandafter\expandafter\expandafter\def% \expandafter\expandafter\expandafter#2% \expandafter\expandafter\expandafter{% \expandafter@firstoffive#2}}% <-------- five \def\cpageref@getref#1#2{% \expandafter\let\expandafter#2\csname r@#1@cref\endcsname% \expandafter\expandafter\expandafter\def% \expandafter\expandafter\expandafter#2% \expandafter\expandafter\expandafter{% \expandafter@secondoffive#2}}% <----------- five

\AtBeginDocument{% \def\label@noarg#1{% \cref@old@label{#1}% @bsphack% \edef@tempa{{page}{\the\c@page}}% \setcounter{page}{1}% \edef@tempb{\thepage}% \expandafter\setcounter@tempa% \cref@constructprefix{page}{\cref@result}% \protected@write@auxout{}% {\string\newlabel{#1@cref}{{\cref@currentlabel}% {[@tempb][\arabic{page}][\cref@result]\thepage}{}{}{}}}% <----- five @esphack}% \def\label@optarg[#1]#2{% \cref@old@label{#2}% @bsphack% \edef@tempa{{page}{\the\c@page}}% \setcounter{page}{1}% \edef@tempb{\thepage}% \expandafter\setcounter@tempa% \cref@constructprefix{page}{\cref@result}% \protected@edef\cref@currentlabel{% \expandafter\cref@override@label@type% \cref@currentlabel@nil{#1}}% \protected@write@auxout{}% {\string\newlabel{#2@cref}{{\cref@currentlabel}% {[@tempb][\arabic{page}][\cref@result]\thepage}{}{}{}}}% <------- five @esphack}% }
\begin{document}

\Cref{sec:one}

\end{document}

Ulrike Fischer
  • 327,261
  • 3
    \labelformat is also a step in the right direction. Hopefully one day all these packages will be consolidated in either hyperref or the kernel. – yannisl Feb 01 '24 at 13:12
  • 1
    Thank you for digging through this. I hope some fix can be added to cleveref at some stage. – Andrew Swann Feb 01 '24 at 13:29
  • Any chance this is fixed before the upcoming TexLive 2024 release? – Flow Mar 06 '24 at 14:20
  • @Flow the maintainer has been notified but I don't know if and if yes when he will fix it, you will have to ask him directly. If nothing happens we will probably add a firstaid to the next LaTeX release as a temporary fix. – Ulrike Fischer Mar 06 '24 at 14:32
  • What's the recommended cleveref alternative these days, if any? – Flow Mar 06 '24 at 14:36
  • @flow don't ask such follow up questions in comments. That pings only me and so requests personal support. Ask a proper question. – Ulrike Fischer Mar 06 '24 at 14:42
  • 1
    I am sorry, you are right. I will ask this as a new question. However, I have two more questions regarding your answer: 1. Where does your code after the \makeatletter belong: into the main document, into the subfile document, or in both? 2. I remember that \makeatletter is usually paired with \makeatother, isn't this here required? – Flow Mar 07 '24 at 07:38