% \iffalse meta-comment
%
%% File: latex-lab-bib.dtx (C) Copyright 2023-2026 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
%
% The latex-lab bundle is developed in the LaTeX2e GitHub.
% Issues may be reported at
%
%    https://github.com/latex3/latex2e/issues
%
\def\ltlabbibdate{2026-04-27}
\def\ltlabbibversion{0.81e}
%<*driver>
\DocumentMetadata{tagging=on,pdfstandard=ua-2}
\documentclass{l3in2edoc}
\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{latex-lab-bib.dtx}
\end{document}
%</driver>
%
% \fi
%
% \title{The \textsf{latex-lab-bib} package\\
% Changes and additions to the kernel related to tagging and links in citations and 
% bibliography entries}
% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}}
% \date{v\ltlabbibversion\ \ltlabbibdate}
%
% \maketitle
%
% \providecommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}}
%
% \begin{abstract}
% \end{abstract}
%
% \section{Introduction}
%
% The followings contains small changes to improve tagging of
% bibliography entries and citations. 
% 
% The tagging of the standard bibliography is actually quite straightforward:
% A bibliography is typically a list with a heading and the code which tags sectioning
% commands and lists handles that. 
% 
% There are here only two problems: 
% 
% \begin{itemize}
% \item The structure number of the \texttt{LI} element
% created by a \cs{bibitem} must be recorded somehow to allow to reference it in 
% a \cs{cite}. 
% \item \pkg{hyperref} redefines the item command and so breaks the list structure
% see \url{https://github.com/latex3/latex2e/discussions/1010#discussioncomment-5565418}
% \end{itemize}
% 
% Both problems are rather easy to resolve, but it must be checked if other packages 
% interfere again by redefining the commands.
% 
% More difficult is the tagging of citation commands. Citations should be inside 
% a Reference structure and contain a /Ref entry pointing to the relevant 
% item in the bibliography. For simple citations like 
% \enquote{[1]} or \enquote{Doody (2023)} this is easy, but it is not obvious how
% to handle combined citations like \enquote{Doody (2003,2018)} (or even compressed citations
% like \enquote{[1-3]}). The current implementation follows the links: whatever \pkg{hyperref} would
% link is set as the reference.
% 
% There exist various packages which over the years tried to improve and extend
% the bibliography commands. We discuss here three: \pkg{natbib}, \pkg{chapterbib} and \pkg{biblatex}.
% 
% \begin{description}
% \item[\pkg{natbib}] It is rather easy to support \pkg{natbib}: it has hooks for links and the tagging code
% can follow. Only a bit coordination with \pkg{hyperref} is needed to avoid that \pkg{hyperref}
% remove the tagging code again.
% 
% \item[chapterbib] In standard LaTeX every bib entry has an unique label which points to the 
% (mandatory and unique) bibliography and the target created by \pkg{hyperref} 
% has the simple form \texttt{cite.}\meta{key}.
% If a package that support multiple bibliographies is used (e.g. chapterbib)
% this is no longer works: a bib entry \texttt{doody} 
% can in one chapter get the label \enquote{[1]}
% and in the other \enquote{[5]} or even \enquote{Doo19} and naturally links
% should jump to the relevant chapter bibliography. chapterbib solves this
% by creating bib keys with a suffix: when reading the \texttt{.aux} files it will
% create the keys \texttt{doody@-1} and \texttt{doody@-2} where the number is related
% to the chapter/include, and in the document and in the document \verb+\cite{doody}+
% will look for \texttt{doody@-1} and \texttt{doody@-2} depending on the number of the
% current include. For some unknown reason chapterbib uses two commands
% to handle the suffix: the command \cs{@extra@binfo} is written to the aux-files 
% and used when processing the \cs{bibcite} commands, 
% but in the document \cs{@extra@b@citeb} is used. Supporting this is 
% straightforward: one only has to take care that the tagging code uses
% \cs{@extra@b@citeb} in the relevant places too.
% 
% \item[\pkg{biblatex}] \pkg{biblatex} supports multiple bibliographies out-of-the-box. 
% It numbers the link target by refsection and uses then the name
% \verb+\the\c@refsection @+\meta{key}.
% 
% Printing a bibliography is not required, in this case you get an engine warning
% and links jump to the begin of the document:
% \begin{verbatim}
% name{cite.0@doody} has been referenced but does not exist
% \end{verbatim}
% 
% Bibliographies can be printed more than once by refsection. To avoid duplicated
% target, \pkg{biblatex} stores the names of the targets in a list and if later
% it detects that a target name has already been used in a
% bibliography no new target is created for this item. This means a citation
% will normally jump to the first bibliography which shows the entry.
% 
% The tagging code has to mimic this code. This means that it can't label every item,
% but has to test if this anchor is already known.
% \end{description}
% 
% \section{Provided or redefined commands}
%
% \begin{function}{\@extra@binfo,\@extra@b@citeb}
% 
% These are taken from \pkg{hyperref}, they are for chapterbib compatibility (and also
% signal to chapterbib not to change the citation commands)
% \end{function}
% 
% \begin{function}{\@bibitem,\@lbibitem}
% The internal item commands. 
% \end{function}
% 
% \section{Implementation}
%    \begin{macrocode}
%<*package>
%<@@=tag>
%    \end{macrocode}
% \changes{v0.81e}{2026-04-27}{Revised implementation.}
%    \begin{macrocode}
\ProvidesExplPackage {latex-lab-testphase-bib} {\ltlabbibdate} {\ltlabbibversion}
  {Code related to the tagging of bibliography and cite command}
%    \end{macrocode}
%
%
% \begin{macro}{\@extra@binfo,\@extra@b@citeb}
% These are taken from \pkg{hyperref}, they are for chapterbib compatibility (and also
% signal to chapterbib not to change the citation commands)
%    \begin{macrocode}
\providecommand*\@extra@binfo{}%
\providecommand\@extra@b@citeb{}
%    \end{macrocode}
% \end{macro}
% 
% 
%\subsection{Handling the bibliography}
% \begin{macro}{\@lbibitem}
% This is the command used if \cs{bibitem} has an optional argument. 
% 
% The link target is now added by the block code in the \cs{item} command (as long as the
% bibliography is built as a list). 
% We only need to change the name.
% This also works if \pkg{hyperref} is not loaded as the kernel \cs{MakeLinkTarget} also contains
% the \texttt{target/setname/after} hook. 
% 
%    \begin{macrocode}  
\AddToHookWithArguments{cmd/@lbibitem/before}[latex-lab-testphase-bib/target]
 { 
   \ExpandArgs{e}\NextLinkTarget{cite.#2\@extra@b@citeb}
 }
%    \end{macrocode} 
% We make a copy to be able to reinstate the definition. This is, e.g.,
% currently needed with \pkg{hyperref}.
%    \begin{macrocode}
\let\@kernel@copy@lbibitem\@lbibitem       
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\@bibitem}
% Similar for \cs{@bibitem}. 
%
% The target is added by the block code. We only need to change the name.
%    \begin{macrocode}   
\AddToHookWithArguments{cmd/@bibitem/before}[latex-lab-testphase-bib/target]
 {
   \ExpandArgs{e}\NextLinkTarget{cite.#1\@extra@b@citeb}
 }
%    \end{macrocode}  
%    \begin{macrocode}
\let\@kernel@copy@bibitem\@bibitem           
%    \end{macrocode}
% \end{macro}
 %
% \subsection{Handling citation commands}
% We redefine similar to \pkg{hyperref} the \cs{bibcite} command to inject link and
% structure. Even if it looks a bit odd it is now used for many years and so 
% hopefully compatible with various packages. But differently to \pkg{hyperref} we use
% the new hooks with arguments.
% TODO: consider hook name. 
%    \begin{macrocode}
\NewMirroredHookPairWithArguments{bibcite/before}{bibcite/after}{2}  
\def\bibcite#1#2{%
   \@newl@bel{b}{#1\@extra@binfo}{%
      \UseHookWithArguments{bibcite/before}{2}{#1}{#2}
       #2
      \UseHookWithArguments{bibcite/after}{2}{#1}{#2} 
       }%
     }% 
\let\@kernel@copy@bibcite\bibcite         
%    \end{macrocode}
% Now we add the tagging structure. The target is in the structure of the label,
% so we use the tagpdf command that retrieve the parent structure, i.e., the \texttt{LI}.
%    \begin{macrocode}
\NewTaggingSocket{bib/cite/before}{1}
\NewTaggingSocketPlug{bib/cite/before}{kernel}
 {
    \tag_mc_end_push:
    \tagstructbegin{tag=\UseStructureName{cite}}
    \tag_struct_gput:nne{\tag_get:n{struct_num}}{ref_dest_parent}{#1}
    \tagmcbegin{}
 }
\AssignTaggingSocketPlug{bib/cite/before}{kernel} 
\AddToHookWithArguments{bibcite/before}
  {
    \UseTaggingSocket{bib/cite/before}{cite.#1\@extra@b@citeb}
  }
\AddToHookWithArguments{bibcite/after}
  {
    \UseTaggingSocket{inline/end}
  }
%    \end{macrocode}
% 
% The package \pkg{hyperref} uses the hook too and the link will be inside the reference.
%
% \subsection{\pkg{natbib} and \pkg{biblatex} support}
%  Both \pkg{natbib} and \pkg{biblatex} use \cs{hyper@natlinkstart}, \cs{hyper@natlinkend} 
%  and \cs{hyper@natanchorstart} to handle the links and anchors. The commands can be also
%  used to handle tagging, both if \pkg{hyperref} is loaded and if not. We only need to ensure
%  that they use \cs{MakeLinkTarget} also if \pkg{hyperref} is not active (and that \pkg{hyperref}
%  does not overwrite that again if used).
%  
%  \pkg{natbib} calls \verb+\hyper@natanchorstart{key\@extra@b@citeb}+. With \pkg{hyperref} loaded this
%  gives the anchor \verb+cite.key\@extra@b@citeb+.
%  \pkg{biblatex} calls \verb+\hyper@natanchorstart{\the\c@refsection @\abx@field@entrykey}+
%  and this gives \verb+cite.\the\c@refsection @\abx@field@entrykey+.
%  
%  We assume that no document loads both package -- that will probably break.
%    \begin{macrocode}
\newcommand\hyper@natlinkstart[1]{}
\newcommand\hyper@natlinkend{}
\newcommand\hyper@natanchorstart[1]{}
%    \end{macrocode}
% We overwrite the anchor command at begin document so that this is also used with \pkg{hyperref}.
%    \begin{macrocode}
\AtBeginDocument{\renewcommand\hyper@natanchorstart[1]{\MakeLinkTarget*{cite.#1}}}
%    \end{macrocode}
%
% The code for the citations can be shared by both packages, as they both use the
% \pkg{natbib} hooks. 
% The structure this references is currently the
% itemlabel for \pkg{natbib}, and the itembody for \pkg{biblatex}. TODO: move this up one level.
% \changes{0.81e}{2026-04-27}{Remove \cs{@extra@b@citeb}, tagging issue \#1282}
%    \begin{macrocode}
\AddToHookWithArguments{cmd/hyper@natlinkstart/before}
 {
   \leavevmode
   \UseTaggingSocket{bib/cite/before}{cite.#1}
 }
\AddToHook{cmd/hyper@natlinkend/after}
 {
   \UseTaggingSocket{inline/end}
 }
      
%    \end{macrocode}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
