% \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} % % % \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} % % \end{macrocode}