Estoy intentando utilizar Cleveref para hacer referencias cruzadas entre documentos y compilarlos con make4ht. El siguiente ejemplo se compila con pdflatex pero no con make4ht o htlatex.
main.tex
:
\documentclass{article}
\usepackage{hyperref}
\usepackage{cleveref}
\begin{document}
\section{First Section} \label{section}
\begin{equation} \label{equation}
\int f(x) dx
\end{equation}
\end{document}
ref.tex
:
\documentclass{article}
\usepackage{amsmath}
\usepackage{xr-hyper}
\usepackage{hyperref}
\usepackage{cleveref}
\externaldocument[main-]{main}
\begin{document}
Equation \eqref{main-equation} in \cref{main-section}.
\end{document}
Si cambio \cref
a \ref
(dejo de usar Cleveref), make4ht todavía no puede compilar sin dar un error.
[ERROR] htlatex: ./ref.tex 10 Argument of \XR:rEfLiNK has an extra }.
Si se compila utilizando el modo por lotes, se produce el html esperado. Si intento compilar \cref
, obtengo muchos más errores y las referencias no funcionan si se usa el modo por lotes. Si compilo ref.tex
antes main.tex
, no hay errores, pero obviamente la referencia cruzada no funciona.
Solía haber un error casi idéntico con make4ht xr-hyper e hyperref discutidosaquíque desde entonces ha sido solucionado.
¿Alguien conoce una solución para esto? Además, ¿a qué proyecto sería bueno informar el error?
Respuesta1
Hay dos problemas. La primera es que TeX4ht necesita cargar el aux
archivo desde main.tex
. Cuando hace esto, verifica todas las etiquetas y las modifica para que produzcan enlaces correctos al main.html
archivo. Sin embargo, Cleveref utiliza etiquetas especiales con metainformación sobre el tipo de referencia de la etiqueta dada. Estas etiquetas especiales utilizan el sufijo @cref
. Tenemos que ignorarlos. Esta versión del xr-hyper.4ht
archivo hace eso:
% xr-hyper.4ht (2023-03-10-16:43), generated from tex4ht-4ht.tex
% Copyright 2003-2009 Eitan M. Gurari
% Copyright 2009-2023 TeX Users Group
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either
% version 1.3c of this license or (at your option) any
% later version. The latest version of this license is in
% http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions
% of LaTeX version 2005/12/01 or later.
%
% This work has the LPPL maintenance status "maintained".
%
% The Current Maintainer of this work
% is the TeX4ht Project <http://tug.org/tex4ht>.
%
% If you modify this program, changing the
% version identification would be appreciated.
\immediate\write-1{version 2023-03-10-16:43}
\let\XR:loop=\XR@loop
\def\XR@loop#1{%
\def\:temp##1.aux{\openin15=##1.xref
\ifeof15
\:warning{missing ##1.xref for ##1.aux}%
\let\:temp\empty
\else
\def\:temp{\input ##1.xref}%
\fi
\closein15 \:temp
}%
\catcode`\:=11
\expandafter\ifx \csname xr:CrossWord\endcsname\relax
\let\xr:CrossWord=\Cross:Word
\def\Cross:Word##1##2{%
\expandafter\let\csname cw:\cw:format{##1##2}\endcsname\:UnDef
\xr:CrossWord{##1}{##2}}%
\fi
%
\:temp#1%
\catcode`\:=12
\XR:loop{#1}%
}
\ExplSyntaxOn
\long\def\XR@test#1#2#3#4\XR@{%
\ifx#1\newlabel
\regex_match:nnTF{@cref}{#2}% we must handle cleveref meta references
{\expandafter\xdef\csname r@\XR@prefix#2\endcsname{#3}}%
{\expandafter\xdef\csname r@\XR@prefix#2\endcsname{\XR:rEfLiNK #3}}%
%
\else\ifx#1\@input
\edef\XR@list{\XR@list#2\relax}%
\fi\fi
\ifeof\@inputcheck\expandafter\XR@aux
\else\expandafter\XR@read\fi}
\ExplSyntaxOff
\def\XRrEfLiNK[#1]#2#3{%
\filename@parse{#1}% Get basename of the linked html file,
% xr:dir\filename@base contains file's directory
\a:xr[\csname xr:dir:\filename@base\endcsname#1]{#2}{}%
% this extra \fi fixes warning about unclosed \ifx, I hope it doesn't break anything
% I cannot find where that \ifx starts
\ifx\hyperrefLabel\:UnDef #3\else \hyperrefLabel\fi \b:xr\fi}
\NewConfigure{xr}{2}
\Configure{xr}{\Link}{\EndLink}
\def\XR:rEfLiNK#1#2#3#4#5{{\xr:rEfLiNK#1}{\xr:rEfLiNK#2}{\xr:rEfLiNK#3}}
\def\xr:rEfLiNK#1#2{\noexpand\XRrEfLiNK[\Get:HFile#2-]{#2}}
\def\Get:HFile#1-#2-{\:LikeRef{)F\:gobble #1F-}}
\Hinput{xr}
\endinput
El código importante es este:
\ExplSyntaxOn
\long\def\XR@test#1#2#3#4\XR@{%
\ifx#1\newlabel
\regex_match:nnTF{@cref}{#2}% we must handle cleveref meta references
{\expandafter\xdef\csname r@\XR@prefix#2\endcsname{#3}}%
{\expandafter\xdef\csname r@\XR@prefix#2\endcsname{\XR:rEfLiNK #3}}%
%
\else\ifx#1\@input
\edef\XR@list{\XR@list#2\relax}%
\fi\fi
\ifeof\@inputcheck\expandafter\XR@aux
\else\expandafter\XR@read\fi}
\ExplSyntaxOff
Utiliza la expresión regular LaTeX 3 para detectar @cref
etiquetas y declara la referencia dada en consecuencia.
El otro problema está en cleveref.4ht
, porque necesitamos admitir los enlaces de archivos externos especiales introducidos en la función anterior. Esta versión de cleveref.4ht
debería solucionar eso:
% cleveref.4ht (2023-03-10-17:14), generated from tex4ht-4ht.tex
% Copyright 2018-2023 TeX Users Group
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either
% version 1.3c of this license or (at your option) any
% later version. The latest version of this license is in
% http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions
% of LaTeX version 2005/12/01 or later.
%
% This work has the LPPL maintenance status "maintained".
%
% The Current Maintainer of this work
% is the TeX4ht Project <http://tug.org/tex4ht>.
%
% If you modify this program, changing the
% version identification would be appreciated.
\immediate\write-1{version 2023-03-10-17:14}
% orig:refstepcounter is saved in cleveref-hooks.4ht
\let\cref@old@refstepcounter\orig:refstepcounter%
\def\refstepcounter{%
\@ifnextchar[{\refstepcounter@optarg}{\refstepcounter@noarg}%]
}%
% fix for TeX4ht label mechanism
\def\cref:currentlabel#1{\let\cnt:currentlabel\@currentlabel
\def\:@currentlabel{\ifx \cnt:currentlabel\@currentlabel
\expandafter\the\csname c@#1\endcsname\else \@currentlabel\fi}%
%
\anc:lbl r{#1}%
}
\def\refstepcounter@noarg#1{%
\cref@old@refstepcounter{#1}%
\cref@constructprefix{#1}{\cref@result}%
\@ifundefined{cref@#1@alias}%
{\def\@tempa{#1}}%
{\def\@tempa{\csname cref@#1@alias\endcsname}}%
\protected@xdef\cref@currentlabel{%
[\@tempa][\arabic{#1}][\cref@result]%
\csname p@#1\endcsname\csname the#1\endcsname}%
\cref:currentlabel{#1}%
}%
\def\refstepcounter@optarg[#1]#2{%
\cref@old@refstepcounter{#2}%
\cref@constructprefix{#2}{\cref@result}%
\@ifundefined{cref@#1@alias}%
{\def\@tempa{#1}}%
{\def\@tempa{\csname cref@#1@alias\endcsname}}%
\protected@xdef\cref@currentlabel{%
[\@tempa][\arabic{#2}][\cref@result]%
\csname p@#2\endcsname\csname the#2\endcsname}%
\cref:currentlabel{#2}%
}%
\ifdefined\@firstoffive\else%
\def\@firstoffive#1#2#3#4#5{#1}%
\fi
\def\:tempa#1#2{\bgroup%
\def\rEfLiNK##1##2{\Link{##1}{}}%
\def\XRrEfLiNK[##1]##2##3{\Link[##1]{##2}{}}% handle links from Xr and Xr-hyper
\expandafter\expandafter\expandafter\@firstoffive\csname r@#2\endcsname{}{}{}{}{}%
\cref@getlabel{#2}{\@templabel}%
#1{\@templabel}{}{}%
\EndLink\egroup%
}%
\HLet\@@@setcref=\:tempa
\@ifpackageloaded{amsthm}{
\let\cref@thmnoarg\@thm%
\def\@thm{\@ifnextchar[{\cref@thmoptarg}{\cref@thmnoarg}}%]
\def\:tempb[#1]#2#3#4{%
% call original amsthm theorem definition, but
% disable \:thm in order to prevent infinite loop
\let\:thm\:gobble%
\cref@thmnoarg{#2}%
\o:cref@thmoptarg:[#1]{#2}{#3}{#4}
}%
\HLet\cref@thmoptarg\:tempb%
}{}%
\Hinput{cleveref}
\endinput
El código importante es este:
\def\:tempa#1#2{\bgroup%
\def\rEfLiNK##1##2{\Link{##1}{}}%
\def\XRrEfLiNK[##1]##2##3{\Link[##1]{##2}{}}% handle links from Xr and Xr-hyper
\expandafter\expandafter\expandafter\@firstoffive\csname r@#2\endcsname{}{}{}{}{}%
\cref@getlabel{#2}{\@templabel}%
#1{\@templabel}{}{}%
\EndLink\egroup%
}%
\HLet\@@@setcref=\:tempa
Necesitamos declarar \def\XRrEfLiNK[##1]##2##3
aquí.
Con estos cambios, debería poder compilar su ejemplo: