T-F-S / tcolorbox

A LaTeX package to create highly customizable colored boxes.
http://www.ctan.org/pkg/tcolorbox
LaTeX Project Public License v1.3c
213 stars 15 forks source link

`label is zlabel` makes hyper references undefined in some circumstances #237

Closed dbitouze closed 1 year ago

dbitouze commented 1 year ago

I want a complement (for “additional information”) environment to display:

  1. a “title“ (at its insertion location)
  2. (and just after) a (fixed) text which is an hyperlink to:
  3. a tcolorbox (postponed at the end of the document) containing the environment body (which consists of the additional information).

By contrast to the examples of exercises and solutions in the section 8 “Recording” of the tcolorbox' documentation, I want the additional information to be store in expl3 sequences instead of external files.

A MCE of such an environment is the following:

\documentclass{article}
\usepackage{lipsum}
\usepackage{tcolorbox}
\usepackage{zref-clever}
\usepackage{hyperref}

% \tcbset{label is zlabel}

\ExplSyntaxOn

\seq_new:N \g__complement_titles_seq
\seq_new:N \g__complement_contents_seq

\int_new:N \g__complement_int
\int_new:N \g__complement_bis_int

\NewDocumentEnvironment{complement}{ m +b }{
  \int_gincr:N \g__complement_int
  \seq_gput_right:Nn \g__complement_titles_seq {
    #1
  }
  \seq_gput_right:Nn \g__complement_contents_seq {
    #2
  }
  \par
  \medskip
  \bfseries
  \hypertarget{__back_to_text_\int_use:N\g__complement_int}{
    #1~
    \hyperref[__complement_\int_use:N\g__complement_int]{(click~ here)}.
  }
  \medskip{}
}{
}

\newtcolorbox[auto~ counter]{__complement_box}[1][]{
  fonttitle=\bfseries,
  #1
}

\AddToHook{cmd/enddocument/before}{
  \seq_map_inline:Nn \g__complement_contents_seq {
    \int_gincr:N \g__complement_bis_int
    \begin{__complement_box}[
      , label={__complement_\int_use:N\g__complement_bis_int}
      , title=\seq_item:Nn \g__complement_titles_seq {\g__complement_bis_int}
      , after~ upper=\c_space_tl\hyperlink{__back_to_text_\int_use:N\g__complement_bis_int}{(Back~ to~ text.)}
    ]
      #1
    \end{__complement_box}
  }
}
\ExplSyntaxOff
\begin{document}
\lipsum[1]

\begin{complement}{Additional informations about \texttt{tcolorbox}}
  \lipsum[1]
\end{complement}

\lipsum[1]

\begin{complement}{Additional informations about \texttt{zref-clever}}
\lipsum[1]
\end{complement}

\lipsum[1]
\end{document}

That works pretty well, except if the \tcbset{label is zlabel} code is uncommented: in such a case, the texts “(click here)” are not hyperlinks anymore.

T-F-S commented 1 year ago

I think, this is correct behaviour, because zlabel is label transforms the label option into a zlabel. According to the hyperref documentation \hyperref[label]{text} works for a label (only). Maybe, it would be a good think, if hyperref supports zlabel in future?

For your application, I would recommend to replace label by hypertarget. Also, this would make your linking mechanism symmetric.

Try the following:

\documentclass{article}
\usepackage{lipsum}
\usepackage{tcolorbox}
\usepackage{zref-clever}
\usepackage{hyperref}

\tcbset{label is zlabel}

\ExplSyntaxOn

\seq_new:N \g__complement_titles_seq
\seq_new:N \g__complement_contents_seq

\int_new:N \g__complement_int
\int_new:N \g__complement_bis_int

\NewDocumentEnvironment{complement}{ m +b }{
  \int_gincr:N \g__complement_int
  \seq_gput_right:Nn \g__complement_titles_seq {
    #1
  }
  \seq_gput_right:Nn \g__complement_contents_seq {
    #2
  }
  \par
  \medskip
  \bfseries
  \hypertarget{__back_to_text_\int_use:N\g__complement_int}{
    #1~
    \hyperlink{__complement_\int_use:N\g__complement_int}{(click~ here)}.
  }
  \medskip{}
}{
}

\newtcolorbox[auto~ counter]{__complement_box}[1][]{
  fonttitle=\bfseries,
  #1
}

\AddToHook{cmd/enddocument/before}{
  \seq_map_inline:Nn \g__complement_contents_seq {
    \int_gincr:N \g__complement_bis_int
    \begin{__complement_box}[
      , hypertarget={__complement_\int_use:N\g__complement_bis_int}
      , title=\seq_item:Nn \g__complement_titles_seq {\g__complement_bis_int}
      , after~ upper=\c_space_tl\hyperlink{__back_to_text_\int_use:N\g__complement_bis_int}{(Back~ to~ text.)}
    ]
      #1
    \end{__complement_box}
  }
}
\ExplSyntaxOff
\begin{document}
\lipsum[1]

\begin{complement}{Additional informations about \texttt{tcolorbox}}
  \lipsum[1]
\end{complement}

\lipsum[1]

\begin{complement}{Additional informations about \texttt{zref-clever}}
\lipsum[1]
\end{complement}

\lipsum[1]
\end{document}

This works for label and for zlabel (because neither is needed).